Анимация бывает только один раз - PullRequest
0 голосов
/ 25 мая 2019
public static Animator zoomInImage(ImageView smallImage, ImageView largeImage, long duration) {
    Rect startBounds    = new Rect();
    Rect endBounds      = new Rect();
    Point globalOffset  = new Point();

    smallImage.getGlobalVisibleRect(startBounds);
    largeImage.getGlobalVisibleRect(endBounds, globalOffset);

    startBounds.offset(-globalOffset.x, -globalOffset.y);
    endBounds.offset(-globalOffset.x, -globalOffset.y);

    float startScale;
    if ((float) endBounds.width() / endBounds.height()
            > (float) startBounds.width() / startBounds.height()) {
        // Extend start bounds horizontally
        startScale = (float) startBounds.height() / endBounds.height();
        float startWidth = startScale * endBounds.width();
        float deltaWidth = (startWidth - startBounds.width()) / 2;
        startBounds.left -= deltaWidth;
        startBounds.right += deltaWidth;
    } else {
        // Extend start bounds vertically
        startScale = (float) startBounds.width() / endBounds.width();
        float startHeight = startScale * endBounds.height();
        float deltaHeight = (startHeight - startBounds.height()) / 2;
        startBounds.top -= deltaHeight;
        startBounds.bottom += deltaHeight;
    }

    smallImage.setAlpha(0f);


    largeImage.setPivotX(0f);
    largeImage.setPivotY(0f);

    AnimatorSet animatorSet = new AnimatorSet();

    animatorSet
            .play(ObjectAnimator.ofFloat(largeImage, View.X, startBounds.left, endBounds.left))
            .with(ObjectAnimator.ofFloat(largeImage, View.Y, startBounds.top, endBounds.top))
            .with(ObjectAnimator.ofFloat(largeImage, View.SCALE_X, startScale, 1f))
            .with(ObjectAnimator.ofFloat(largeImage, View.SCALE_Y, startScale, 1f));

    animatorSet.setDuration(duration);
    animatorSet.setInterpolator(new DecelerateInterpolator());
    animatorSet.start();
    largeImage.setVisibility(View.VISIBLE);
    return animatorSet;

}


public static Animator zoomOutImage(final ImageView smallImage, final ImageView largeImage, long duration) {
    Rect startBounds    = new Rect();
    Rect endBounds      = new Rect();
    Point globalOffset  = new Point();

    smallImage.getGlobalVisibleRect(startBounds);
    largeImage.getGlobalVisibleRect(endBounds, globalOffset);

    startBounds.offset(-globalOffset.x, -globalOffset.y);
    endBounds.offset(-globalOffset.x, -globalOffset.y);

    float startScale;
    if ((float) endBounds.width() / endBounds.height()
            > (float) startBounds.width() / startBounds.height()) {
        // Extend start bounds horizontally
        startScale = (float) startBounds.height() / endBounds.height();
        float startWidth = startScale * endBounds.width();
        float deltaWidth = (startWidth - startBounds.width()) / 2;
        startBounds.left -= deltaWidth;
        startBounds.right += deltaWidth;
    } else {
        // Extend start bounds vertically
        startScale = (float) startBounds.width() / endBounds.width();
        float startHeight = startScale * endBounds.height();
        float deltaHeight = (startHeight - startBounds.height()) / 2;
        startBounds.top -= deltaHeight;
        startBounds.bottom += deltaHeight;
    }

    largeImage.setPivotX(0f);
    largeImage.setPivotY(0f);

    AnimatorSet animatorSet = new AnimatorSet();

    animatorSet
            .play(ObjectAnimator.ofFloat(largeImage, View.X, startBounds.left))
            .with(ObjectAnimator.ofFloat(largeImage, View.Y, startBounds.top))
            .with(ObjectAnimator.ofFloat(largeImage, View.SCALE_X, startScale))
            .with(ObjectAnimator.ofFloat(largeImage, View.SCALE_Y, startScale));

    animatorSet.setDuration(duration);
    animatorSet.setInterpolator(new DecelerateInterpolator());
    animatorSet.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            smallImage.setAlpha(1f);
            largeImage.setVisibility(View.INVISIBLE);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            smallImage.setAlpha(1f);
            largeImage.setVisibility(View.INVISIBLE);
        }
    });
    animatorSet.start();

    return animatorSet;
}

Две вышеуказанные функции предназначены для анимации zoomIn и zoomOut изображения.Проблема с приведенным выше кодом заключается в том, что анимация zoomIn происходит один раз в начале, но не в более позднее время.Пока zoomOut работает.Функция zoomIn и zoomOut вызывается при нажатии кнопки на изображении.

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

Я называю это так

lImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (currentAnim != null) currentAnim.cancel();
        currentAnim = ZoomAnimator.zoomOutImage(sImageView, lImageView, getResources().getInteger(
                android.R.integer.config_shortAnimTime));
    }
});

sImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (currentAnim != null) currentAnim.cancel();
        currentAnim = ZoomAnimator.zoomInImage(sImageView, lImageView, getResources().getInteger(
                android.R.integer.config_shortAnimTime));
    }
});

1 Ответ

0 голосов
/ 29 мая 2019

Я думаю, что ваша реализация слишком сложна. Попробуйте использовать Transition API из пакета androidx (поддержка), анимация с ним намного проще. Позвоните TransitionManager.beginDelayedTransition и измените масштаб просмотра. По умолчанию ChangeTransform переход, который обрабатывает изменения масштаба.

import androidx.transition.ChangeTransform;
import androidx.transition.Transition;
import androidx.transition.TransitionManager; 

private void onClick() {
    View imageView = findViewById(R.id.imageView);
    ViewGroup parent = findViewById(R.id.parent);

    Transition transition = new ChangeTransform();
    transition.setDuration(600);
    transition.addTarget(R.id.imageView);

    TransitionManager.beginDelayedTransition(parent, transition);
    float scale = zoom ? 1 : 0.5f;
    imageView.setScaleX(scale);
    imageView.setScaleY(scale);
}

R.id.parent является родителем ViewGroup из ImageView. Вот результат:

enter image description here

Классно то, что вы можете нажать на изображение в середине предыдущей анимации. TransitionManager запустит новую анимацию из текущих значений масштаба просмотра.

...