2011-01-10 23 views
7

Ist es möglich, ein Zeichenprogramm zu erstellen, das eine Art von Animation enthält, egal ob es sich um eine Frame-für-Frame-Animation, Rotation usw. handelt, die als XML-Zeichen definiert ist und durch ein einzelnes Drawable-Objekt dargestellt werden kann die Animation im Code?Ist es möglich, ein animiertes Zeichenfeld zu haben?

Wie ich denke, es zu verwenden: Ich habe eine Liste und jedes Element in dieser Liste kann irgendwann irgendwann etwas passiert haben. Während es passiert, möchte ich eine drehende Fortschrittsanimation ähnlich einer unbestimmten ProgressBar haben. Da es auch mehrere davon auf dem Bildschirm gibt, dachte ich, dass sie, wenn sie alle dieselbe Drawable hätten, nur eine Instanz davon im Speicher hätten und ihre Animationen würden synchronisiert werden, so dass Sie nicht eine Menge sich drehender Objekte in verschiedenen Punkten hätten in der drehenden Animation.

Ich bin diesem Ansatz nicht verbunden. Ich versuche nur, die effizienteste Möglichkeit zu finden, mehrere sich drehende Fortschrittsanimationen anzuzeigen und sie idealerweise synchron zu synchronisieren, damit sie konsistent aussehen.

Dank

Als Reaktion auf Sybiam Antwort:

Ich habe versucht, eine RotateDrawable Umsetzung, aber es dreht sich nicht.

Hier ist meine xml für die ziehbar bisher:

<?xml version="1.0" encoding="utf-8"?> 
<rotate xmlns:android="http://schemas.android.com/apk/res/android" 
android:drawable="@drawable/my_drawable_to_rotate" 
android:fromDegrees="0" 
android:toDegrees="360" 
android:pivotX="50%" 
android:pivotY="50%" 
android:duration="800" 
android:visible="true" /> 

habe ich versucht, mit dieser ziehbar als src und Hintergrund eines Image und in beiden Richtungen erzeugen nur ein nicht rotierendes Bild.

Gibt es etwas, das die Bilddrehung starten muss?

+0

Kasse http://stackoverflow.com/a/30901885/1052261 –

Antwort

1

Sie können beginnen, das ProgressBar2 von API Demos Projekt zu studieren (es ist als Teil des SDK verfügbar). Achten Sie besonders auf R.layout.progressbar_2.

7

Drawables

Dort gehen Sie! Und dieses für RotateDrawable. Ich glaube, dass es vom Doc aus ziemlich gut sein sollte. Sie können alles in einer XML-Datei definieren und den Hintergrund einer Ansicht als ziehbares XML festlegen. /drawable/myrotate.xml -> @ Drawable/Myrotate

Bearbeiten: Dies ist eine Antwort, die ich hier gefunden habe. Drawable Rotating around its center Android

Bearbeiten 2: Sie haben Recht, die RotateDrawable scheinen gebrochen. Ich weiß nicht, dass ich es auch versucht habe. Ich habe es noch nicht geschafft, es zu animieren. Aber ich habe es geschafft, es zu drehen. Sie müssen setLevel verwenden, das es dreht. Obwohl es nicht wirklich nützlich aussieht. Ich habe den Code durchsucht und das RotateDrawable erhöht nicht einmal die Animationsdauer und die aktuelle Rotation scheint die Ebene seltsamerweise als Maß für die Rotation zu verwenden. Ich glaube, Sie müssen es mit einem Animation Drawable aber hier wieder verwenden. Es ist einfach für mich abgestürzt. Ich habe dieses Feature noch nicht benutzt, aber geplant, es in Zukunft zu verwenden. Ich habe das Web durchsucht und das RotateDrawable scheint wie fast jedes Drawable-Objekt sehr undokumentiert zu sein.

+0

abprallen versuchte ich mein Glück mit der RotateDrawable und es hat nicht animiert. Mehr Details in meiner ursprünglichen Frage. Irgendeine Idee darüber, was ich falsch mache? – cottonBallPaws

+0

Hast du die Animation gestartet? –

+1

Also muss die RotateDrawable programmatisch gestartet werden? Ich nehme an, dass diese Art des Besiegens den Zweck vereitelt, in xml damit umzugehen. Wie würdest du es anfangen? – cottonBallPaws

15

Ja! Der (undokumentierte) Schlüssel, den ich durch das Lesen des Codes ProgressBar entdeckte, ist, dass Sie Drawable.setLevel() in onDraw() aufrufen müssen, damit die <rotate> Sache irgendeinen Effekt hat.Die ProgressBar funktioniert so etwas wie dieses (extra unwichtig Code weggelassen):

Die ziehbar XML:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item> 
     <rotate 
      android:drawable="@drawable/spinner_48_outer_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="0" 
      android:toDegrees="1080" /> 
    </item> 
    <item> 
     <rotate 
      android:drawable="@drawable/spinner_48_inner_holo" 
      android:pivotX="50%" 
      android:pivotY="50%" 
      android:fromDegrees="720" 
      android:toDegrees="0" /> 
    </item> 
</layer-list> 

In onDraw():

Drawable d = getDrawable(); 
    if (d != null) 
    { 
     // Translate canvas so a indeterminate circular progress bar with 
     // padding rotates properly in its animation 
     canvas.save(); 
     canvas.translate(getPaddingLeft(), getPaddingTop()); 

     long time = getDrawingTime(); 

     // I'm not sure about the +1. 
     float prog = (float)(time % ANIM_PERIOD+1)/(float)ANIM_PERIOD; 
     int level = (int)(MAX_LEVEL * prog); 
     d.setLevel(level); 
     d.draw(canvas); 

     canvas.restore(); 

     ViewCompat.postInvalidateOnAnimation(this); 
    } 

MAX_LEVEL ist eine Konstante, und ist immer 10000 (nach die Dokumente). ANIM_PERIOD ist der Zeitraum Ihrer Animation in Millisekunden.

Leider, da Sie ändern müssen onDraw() Sie können nicht nur dieses ziehbar setzen in ein ImageView seit ImageView nie die ziehbar Ebene ändert. Allerdings können Sie die ziehbar Ebene von außerhalb der ImageView ‚s ändern können. ProgressBar (ab) verwendet einen AlphaAnimation, um den Pegel einzustellen. Sie würden also etwas tun:

mMyImageView.setImageDrawable(myDrawable); 

ObjectAnimator anim = ObjectAnimator.ofInt(myDrawable, "level", 0, MAX_LEVEL); 
anim.setRepeatCount(ObjectAnimator.INFINITE); 
anim.start(); 

Es könnte funktionieren, aber ich habe es nicht getestet.

bearbeiten

Es ist eigentlich eine ImageView.setImageLevel() Methode, so dass es so einfach sein könnte wie:

ObjectAnimator anim = ObjectAnimator.ofInt(myImageVew, "ImageLevel", 0, MAX_LEVEL); 
anim.setRepeatCount(ObjectAnimator.INFINITE); 
anim.start(); 
+0

Gibt es keine Lösung, die nur in XML ist? –

+0

'Drawable.setLevel()' ist bequemer. zB: 'ObjectAnimator.ofInt (drawbar," level ", 0, 10000)' – ipcjs

+0

Das ist ... in meiner Antwort. – Timmmm

2

Hier eine der Möglichkeiten ist, (besonders nützlich, wenn Sie ein Auslosungs irgendwo gesetzt haben und müssen animieren es). Die Idee besteht darin, das Zeichen zu verpacken und mit Animationen zu dekorieren. In meinem Fall hatte ich es zu drehen, so unten Sie Beispielimplementierung finden:

public class RotatableDrawable extends DrawableWrapper { 

    private float rotation; 
    private Rect bounds; 
    private ObjectAnimator animator; 
    private long defaultAnimationDuration; 

    public RotatableDrawable(Resources resources, Drawable drawable) { 
     super(vectorToBitmapDrawableIfNeeded(resources, drawable)); 
     bounds = new Rect(); 
     defaultAnimationDuration = resources.getInteger(android.R.integer.config_mediumAnimTime); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     copyBounds(bounds); 
     canvas.save(); 
     canvas.rotate(rotation, bounds.centerX(), bounds.centerY()); 
     super.draw(canvas); 
     canvas.restore(); 
    } 

    public void rotate(float degrees) { 
     rotate(degrees, defaultAnimationDuration); 
    } 

    public void rotate(float degrees, long millis) { 
     if (null != animator && animator.isStarted()) { 
      animator.end(); 
     } else if (null == animator) { 
      animator = ObjectAnimator.ofFloat(this, "rotation", 0, 0); 
      animator.setInterpolator(new AccelerateDecelerateInterpolator()); 
     } 
     animator.setFloatValues(rotation, degrees); 
     animator.setDuration(millis).start(); 
    } 

    @AnimatorSetter 
    public void setRotation(float degrees) { 
     this.rotation = degrees % 360; 
     invalidateSelf(); 
    } 

    /** 
    * Workaround for issues related to vector drawables rotation and scaling: 
    * https://code.google.com/p/android/issues/detail?id=192413 
    * https://code.google.com/p/android/issues/detail?id=208453 
    */ 
    private static Drawable vectorToBitmapDrawableIfNeeded(Resources resources, Drawable drawable) { 
     if (drawable instanceof VectorDrawable) { 
      Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 
      Canvas c = new Canvas(b); 
      drawable.setBounds(0, 0, c.getWidth(), c.getHeight()); 
      drawable.draw(c); 
      drawable = new BitmapDrawable(resources, b); 
     } 
     return drawable; 
    } 
} 

und kann diese verwenden, wie (Drehwerkzeugleiste Navigation icon 360 Grad):

backIcon = new RotatableDrawable(getResources(), toolbar.getNavigationIcon().mutate()); 
toolbar.setNavigationIcon(backIcon); 
backIcon.rotate(360); 

Es shouldn ‚t schwer sein, ein Verfahren hinzuzufügen, die es unbestimmt (setRepeatMode INFINITE for animator)

+0

Was ist @AnimatorSetter, es wird nicht mit ihm kompiliert. –

+0

instanceof VectorDrawable verursacht einen Absturz auf dem Pre-Lollipop und wird nicht benötigt, es sei denn, es handelt sich um einen Vektor. –

+0

Auch diese Klasse muss in ProGuard aufbewahrt werden. –

0
private ValueAnimator rotateDrawable(RotateDrawable drawable, int fromDegree, int toDegree) { 
    drawable.setFromDegrees(fromDegree); 
    drawable.setToDegrees(toDegree); 
    return ObjectAnimator.ofInt(drawable, "level", 0, 10000); 
} 

Ebene ist der interpulting Wert von 0 bis 100000. die tatsächlichen Animations Werte eingestellt werden durch die Methoden setter drehen

0

können Sie verwenden stateListAnimator

<ImageView 
     android:id="@+id/your_id" 
     android:layout_width="200dp" 
     android:layout_height="200dp" 
     android:src="@drawable/your_drawable" 
     android:stateListAnimator="@anim/bounce" /> 

und

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 

    android:interpolator="@android:anim/bounce"> 
    <translate 
     android:duration="900" 

     android:fromXDelta="100%p" 
     android:toXDelta="0%p" /> 
</set> 
Verwandte Themen