Как изменить длительность анимации Android AnimationDrawable на лету? - PullRequest
13 голосов
/ 07 декабря 2010

Я новичок в платформе Android. Я использую следующее для анимации набора из 16 «кадров» с помощью AminationDrawable в моем приложении:

В файле XML у меня есть:

<animation-list 
      xmlns:android="http://schemas.android.com/apk/res/android" 
      android:oneshot="false">
<item android:drawable="@drawable/image_1" android:duration="200" />
<item android:drawable="@drawable/image_1_25" android:duration="200" /> 
<item android:drawable="@drawable/image_1_5" android:duration="200" />
<item android:drawable="@drawable/image_1_75" android:duration="200" /> 
<item android:drawable="@drawable/image_2" android:duration="200" />
<item android:drawable="@drawable/image_2_25" android:duration="200" /> 
<item android:drawable="@drawable/image_2_5" android:duration="200" />
<item android:drawable="@drawable/image_2_75" android:duration="200" />
<item android:drawable="@drawable/image_3" android:duration="200" />
<item android:drawable="@drawable/image_3_25" android:duration="200" /> 
<item android:drawable="@drawable/image_3_5" android:duration="200" />
<item android:drawable="@drawable/image_3_75" android:duration="200" />
<item android:drawable="@drawable/image_4" android:duration="200" />
<item android:drawable="@drawable/image_4_25" android:duration="200" /> 
<item android:drawable="@drawable/image_4_5" android:duration="200" />
<item android:drawable="@drawable/image_4_75" android:duration="200" /> 
</animation-list>

В коде Java у меня есть следующее

сначала я объявляю класс и добавляю метод onCreate(), в котором я настраиваю анимацию.

public class MyNewActivity extends Activity 
{
    // member variables (accessible from within class methods below).
    AnimationDrawable mainAnimation;
    long mSpeed = 50;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_widget);
        // set up image
        ImageView mainImage = (ImageView) findViewById(R.id.image_widget);
        mainImage.setBackgroundResource(R.drawable.animated_image);
        mainAnimation = (AnimationDrawable) mainImage.getBackground();
    };
<...snip...>

... потом я начинаю рисовать, когда пользователь нажимает кнопку, которую я вызываю, чтобы запустить анимацию:

private void start()
{
    // start the image rotating.
    if (mainAnimation.isRunning())
        mainAnimation.stop();

    int numFrames = mainAnimation.getNumberOfFrames();
    for (int ii = 0; ii < numFrames; ii++ )
    {
        // change the animation speed.
        Drawable d = mainAnimation.getFrame(ii);
        mainAnimation.scheduleDrawable(d, mainAnimation, mSpeed);
    }
}
<...snip...>

Так что в другом месте кода у меня есть место для настройки переменной-члена mSpeed. Если я сделаю это и затем вызову start(), анимация запустится, однако скорость всегда будет одинаковой (по существу, что было определено в XML выше. Мой вопрос, как я могу изменить «продолжительность» кадров для перемещения эта анимация быстрее / медленнее на основе пользовательского ввода? Я не вижу способа изменить состояние «длительности», и предполагалось, что приведенный выше вызов ScheduleDrawable() изменит продолжительность кадров чертежа.

1 Ответ

20 голосов
/ 09 апреля 2011

У меня была та же проблема, но мне удалось ее решить при чтении исходного кода объекта AnimationDrawable путем реализации моего собственного класса AnimationDrawable, который расширяет AnimationDrawable и переопределяет метод Run() и добавляет метод setDuration() позволяет мне установить продолжительность следующим образом:

Изучая оригинальный метод run, мы видим, что он делает то же самое, но вызывая scheduleSelf(this, SystemClock.uptimeMillis() + duration); с продолжительностью, указанной вами при добавлении фрейма, поэтому я изменил его. Я также добавляю продолжительность, потому что я использую то же самое для всех своих кадров, но вы можете использовать массив новой продолжительности.

import android.graphics.drawable.AnimationDrawable;
import android.os.SystemClock;

public class MyAnimationDrawable extends AnimationDrawable {

    private volatile int duration;//its volatile because another thread will update its value
    private int currentFrame;

    public MyAnimationDrawable() {
        currentFrame = 0;
    }

    @Override
    public void run() {
        int n = getNumberOfFrames();
        currentFrame++;
        if (currentFrame >= n) {
            currentFrame = 0;
        }
        selectDrawable(currentFrame);
        scheduleSelf(this, SystemClock.uptimeMillis() + duration);
    }

    public void setDuration(int duration) {
        this.duration = duration;
        //we have to do the following or the next frame will be displayed after the old duration
        unscheduleSelf(this);
        selectDrawable(currentFrame);
        scheduleSelf(this, SystemClock.uptimeMillis()+duration);
    }
}

Это мой первый ответ, поэтому я надеюсь, что он вам поможет, и он хорошо объяснен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...