Применение последовательных анимаций к ImageView в Android

Я хотел бы применить последовательную анимацию (скажем, ScaleAnimation) к ImageView, показывающему изображение ресурса. Анимация запускается кнопкой. Например, я хотел бы постепенно увеличивать изображение при каждом нажатии кнопки.

Я установил fillAfter="true" для анимации. Однако все анимации начинаются с исходного состояния ImageView. Кажется, что ImageView сбрасывает свое состояние, и анимация всегда одна и та же, а не начинается с конечного состояния предыдущей анимации.

Что я делаю неправильно?

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button button = (Button)findViewById(R.id.Button01);
    button.setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {
            animate();

        }});
}

private void animate() {
    ImageView imageView = (ImageView) findViewById(R.id.ImageView01);

    ScaleAnimation scale = new ScaleAnimation((float)1.0, (float)1.5, (float)1.0, (float)1.5);
    scale.setFillAfter(true);
    scale.setDuration(500);
    imageView.startAnimation(scale); 
}

person hpique    schedule 01.04.2010    source источник


Ответы (2)


Кажется, что ImageView сбрасывает свое состояние, и анимация всегда одна и та же, а не начинается с конечного состояния предыдущей анимации.

Точно! Я уверен, что для fillAfter="true" есть применение, но я еще не понял, в чем его смысл.

Что вам нужно сделать, так это настроить AnimationListener для каждого релевантного Animation и сделать что-то в onAnimationEnd() слушателя, чтобы фактически сохранить конечное состояние вашей анимации. Я не играл с ScaleAnimation, поэтому я не совсем уверен, каким будет способ «сохранить конечное состояние». Если бы это был AlphaAnimation, идущий от 1.0 к 0.0, вы бы, например, сделали виджет INVISIBLE или GONE в onAnimationEnd().

person CommonsWare    schedule 01.04.2010
comment
Спасибо CommonsWare. Для AlphaAnimation это довольно просто, но для ScaleAnimation и TranslateAnimation такое решение потребует небольшой работы. Любые идеи о том, как справиться с этим? Может быть, это связано с setImageMatrix? - person hpique; 02.04.2010
comment
TranslateAnimation требует, чтобы вы настроили LayoutParams, чтобы повлиять на изменение (например, изменить поля) или, возможно, переместить виджет от одного родителя к другому (через removeView() и addView()). ScaleAnimation...опять же, я им не пользовался, поэтому особых советов у меня нет. Извиняюсь! - person CommonsWare; 02.04.2010
comment
Спасибо еще раз. Я думал о более универсальном решении. Что-то вроде запроса анимации о ее матрице преобразования, а затем применения этой матрицы к представлению. К сожалению, я пока не могу заставить его работать. - person hpique; 02.04.2010

У меня была та же проблема, и я создал следующий код, чтобы легко использовать разные анимации. На данный момент он поддерживает только перевод и альфа-уровни, поскольку я не использовал масштабирование, но его можно легко расширить для поддержки большего количества функций.

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

И логическое значение "doEnd" предназначено для предотвращения переполнения стека при рекурсии (scrollTo вызывает onAnimationEnd по какой-то неясной причине...)

private void setViewPos(View view, Animation anim, long time){
    // Get the transformation
    Transformation trans = new Transformation();
    anim.getTransformation(time, trans);

    // Get the matrix values
    float[] values = new float[9];
    Matrix m = trans.getMatrix();
    m.getValues(values);

    // Get the position and apply the scroll
    final float x = values[Matrix.MTRANS_X];
    final float y = values[Matrix.MTRANS_Y];
    view.scrollTo(-(int)x, -(int)y);

    // Show/hide depending on final alpha level
    if (trans.getAlpha() > 0.5){
        view.setVisibility(VISIBLE);
    } else {
        view.setVisibility(INVISIBLE);       
    }
}

private void applyAnimation(final View view, final Animation anim){
    view.scrollTo(0, 0);
    view.setVisibility(VISIBLE);

    anim.setAnimationListener(new AnimationListener(){
        private boolean doEnd = true;

        @Override
        public void onAnimationEnd(Animation animation) {
            if (doEnd){
                doEnd = false;
                setViewPos(view, animation, anim.getStartTime() + anim.getDuration());
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationStart(Animation animation) {
        }

    });

    view.startAnimation(anim);
}
person Gregory    schedule 10.09.2010