Tween Animation mehrfach laufen lassen

  • Antworten:8
Ralf Züllig
  • Forum-Beiträge: 12

13.11.2010, 11:06:02 via Website

Hallo

Bevor ich mich mit 'richtiger' Grafikprogrammierung via Canvas beschäftige, wollte ich erst einmal die Möglichkeit von Tween Animation ausprobieren. Dies hat eigentlich auch soweit geklappt, das Google Tutorial konnte ich anwenden und auch leicht auf meine Wünsche abändern. Nun wollte ich aber dass die Animation z.B. 10 Mal hintereinander abläuft. Folgendes scheint ja schonmal nicht zu gehen:

1public class Startactivity extends Activity implements OnClickListener {
2
3 private Button hiButton;
4
5 /** Called when the activity is first created. */
6 @Override
7 public void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.main);
10
11 hiButton = (Button) findViewById(R.id.Button01);
12 hiButton.setOnClickListener(this);
13
14 }
15
16 public void onClick(View v) {
17
18 int i = 0;
19 while (i < 10) {
20
21 ImageView image = (ImageView) findViewById(R.id.sgraphic);
22 Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
23 image.startAnimation(hyperspaceJump);
24 i = i + 1;
25
26 TextView takeit = (TextView) findViewById(R.id.TextView01);
27 takeit.setText(String.valueOf(i));
28 }
29 }
30
31}

Die Animation läuft genau einmal ab und nicht mehrmals. Ich hab da offensichtlich noch ein Verständnisproblem, darüber bin ich mir bewusst. Ich habe die letzte Tagen dazu einiges gelesen und wie es scheint muss das mittels Threads ablaufen(?). Ich habe einige Tutorials zu AsyncTask angeschaut und versucht in meinem Code einzubauen, aber leider auch ohne Erfolg.

Kann mir mal bitte jemand verständlich erklären warum obiger Code nicht funktioniert und wie die Lösung meines Problems sein könnte?

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

13.11.2010, 17:44:59 via Website

Ohne mich mit Animationen schon befasst zu haben würde ich davon ausgehen, das diese in eigenen Threads laufen, damit der UI-Thread nicht blockiert wird.
Auf deinen Coe angewendet bedeutet das, das die Zeilen 24 ff bereits ausgeführt werden, bevor die Animation beendet ist, damit auch der Rest der Schleife und es darum am Schirm so aussieht, als ob die Animation nur einmal durchläuft (nämlich nach Beendigung der Schleife).

Antworten
Ansgar M
  • Forum-Beiträge: 1.544

13.11.2010, 18:06:10 via App

Das denke ich auch.
Teste deine Schleife doch mal durch dies in der Schleife:
1Log.v("Mein Log","While-Schleife: i = " +i)
Das Ergebnis siehst du dann im Logcat in Eclipse unter DDMS..
Lg Ansgar

Antworten
Ralf Züllig
  • Forum-Beiträge: 12

13.11.2010, 18:56:47 via Website

Danke soweit für die Antworten. Naja, wie eingangs erwähnt dachte ich mir das schon mit dem Threads, nur wollte ich mir die Peinlichkeit ersparen meinen Versuch mit Threads zu posten. Also eigentlich habe ich das versucht so analog dem Buch "Android: Grundlangen und Programmierung" (S. 132) nachzubauen

1public class Startactivity extends Activity implements OnClickListener, Runnable {
2
3 private Handler handler = new Handler();
4
5 private Button hiButton;
6 public int i = 0;
7
8 /** Called when the activity is first created. */
9 @Override
10 public void onCreate(Bundle savedInstanceState) {
11 super.onCreate(savedInstanceState);
12 setContentView(R.layout.main);
13
14 hiButton = (Button) findViewById(R.id.Button01);
15 hiButton.setOnClickListener(this);
16
17 }
18
19 public void onClick(View v) {
20
21 while (i < 10) {
22 langlaufendeOperation();
23 }
24 }
25
26 public void langlaufendeOperation() {
27
28 Thread thread = new Thread() {
29 public void run() {
30
31 ImageView image = (ImageView) findViewById(R.id.sgraphic);
32 Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
33 image.startAnimation(hyperspaceJump);
34
35 handler.post(callbackviarunnable);
36
37 TextView takeit = (TextView) findViewById(R.id.TextView01);
38 takeit.setText(String.valueOf(i));
39 }
40 };
41 thread.start();
42 }
43
44 private Runnable callbackviarunnable = new Runnable() {
45 public void run() {
46 i = i + 1;
47 }
48 };
49
50}

Fehlermeldungen:
  • Zeile 1: The type startactivity must implement the inherited abstract method Runnable.run()
  • Zeile 32: The method loadAnimation(Context, int) in the type AnimationUtils is not applicable for the arguments (new Thread(){}, int)

Komisch, ich hab ja eine Methode run() implementiert?
Kann gut sein dass der Ansatz total falsch ist, habe nur die Buchvorlage versucht auf meine Situation anzupassen.

— geändert am 13.11.2010, 18:57:14

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

13.11.2010, 19:58:08 via Website

Komisch, ich hab ja eine Methode run() implementiert?

Nicht in der Activity, in der du das behauptet hast ;)
Mach mal das ", Runnable" in Zeile 1 weg.


Zeile 32: The method loadAnimation(Context, int) in the type AnimationUtils is not applicable for the arguments (new Thread(){}, int)

Hatter recht ;)
"this" ist an der Stelle der Thread, und der hat keinen Member "StartAnimation";
Probier mal "Startactivity.this" stattdessen.

Nach meiner Einschätzung wird dieses Konstrukt dein Problem aber nicht lösen, weil es das Ende der Animation nach wie vor nicht "abwartet".

Antworten
Ralf Züllig
  • Forum-Beiträge: 12

13.11.2010, 20:46:20 via Website

Fehlermeldung weg aber Programm verhält sich sehr komisch. Nachdem ich den Button klicke kommt für nen Bruchsekundenteil ne Fehlermeldung und anschliessend bleibt der Buttonknopf noch einige Sekunden lang gedrückt und nach ein paar Sekunden wird der Screen ohne Fehlermeldung einfach schwarz.

Nach meiner Einschätzung wird dieses Konstrukt dein Problem aber nicht lösen, weil es das Ende der Animation nach wie vor nicht "abwartet".

Öhm, naja, dachte was im Runnable abläuft passiert erst nachdem der Thread fertig ist? Und ich zähle ja erst dann den Zähler i eins hoch (Zeile 46).

@Ansgar: Gute Idee. Wie ich ja schon gedacht habe, sobald ich den Button drücke zählt es i halt superschnell auf 10, noch während die Animation (ca. 2s) abläuft. Klicke ich wieder auf den Button läuft die Animation erneut und der Zähler i läuft wieder auf 10. Daher muss wohl ein Thread her, der aber funktioniert :-)

— geändert am 13.11.2010, 20:49:40

Antworten
Ralf Züllig
  • Forum-Beiträge: 12

14.11.2010, 14:00:59 via Website

Gut, nach nochmaligem überlegen ist letzt genannter Code sicher falsch. Überall wo ich zum Thema Thread was gelesen habe stand ja, dass nur der UI-Thread Änderungen an der UI machen darf. Das wäre nun bei mir nicht der Fall, soweit ist mir auch schon klar. Nur ist mir noch keine Lösung eingefallen.

Antworten
Gian U.
  • Forum-Beiträge: 117

16.11.2010, 19:21:10 via Website

Ich hab auch mal ein bisschen mit den Animationen rumgespielt und gemerkt, dass wenn man startAnimation() aufruft, die Animation direkt abgespielt wird und jede andere, die gerade am laufen ist, abgebrochen wird. Bei dir wird so 10 mal sehr kurz hintereinander die gleiche Animation gestartet, so dass es aussieht, als ob nur eine ablaufen würde. Da nützen auch verschiedene Threads nichts...

Ich hab es leider auch nicht hinbekommen, mehrere Animationen vom gleichen Typ hintereinander zu schalten.

Mnemono - Efficient learning!

Antworten
Gelöschter Account
  • Forum-Beiträge: 294

16.11.2010, 23:05:03 via Website

Sorry das ich hier so reinspringe.

Vermeide bitte grundsätzlich langlaufende Tasks in allen Methoden die mit "onXxx" beginnen. Das sind die empfindlichen UI Tasks und werden nach m.W. 5sec abgeschossen. Diese Zeitangabe habe ich mal irgendwo in den Android Docs gelesen und das macht auch Sinn wenn man die alten Messaging Systeme kennt (alter-Sack-Alarm). Die Message Queues sind meist single-threaded und leicht lahm zu legen

Bevor Du Dir die Haare rausreißt und Dich mit den AsyncTasks oder Threads rumschlägst mach mal zunächst folgenden Versuch.

Pack Deine while() Schleife mit dem eingebetteten Code in eine eigene Methode "private void langLaufendeMethode()" und ruf diese am Ende von onCreate auf. Damit testest Du nur ob Deine Methode prinzipiell läuft. Bis hier hin kannst Du Dir sicher sein das die UI für Dich erreichbar ist.

Sobald Du an Die Threads gehst müßtest Du Dir über eines im Klaren sen. Der Thread läuft - auch ohne UI. Jeder Zugriff auf die UI aus dem Thread ist ein Risiko denn die könnte gerade futsch sein und neu aufgebaut werden (Stichwort: Orientation Change).

Gruß
Harald

Antworten