android - 在 ImageView 中为 scaleType ="centerCrop"设置动画

标签 android android-animation android-imageview android-kenburnsview

有没有办法为 scaleType="centerCrop"设置动画?我需要将图像缩放到 certerCrop,以便图像可以覆盖 imageView 的整个区域。但是我需要在图像缩放之前对其进行动画处理以向用户展示图像的实际外观我打算这样做

imageView.animate().scaleX(2.0f).setDuration(2000)

但问题是我将在多个图像上执行此操作以进行幻灯片放映,因此每个图像都有不同的大小和方向。

我也找到了这个图书馆https://github.com/flavioarfaria/KenBurnsView但在使用时仍有问题。

非常感谢任何帮助。

已编辑

开始研究 KenBurnsView 仍然无法将图像平移到中心。

最佳答案

我写了一个自定义ImageView来支持ScaleTypes之间的动画,希望对你有帮助。请原谅我糟糕的英语,它不是我的母语。

用法:

AnimatedImageView animatedImageView = new AnimatedImageView(context) or findViewById(R.id.animated_image_view);
animatedImageView.setAnimatedScaleType(ImageView.ScaleType.CENTER_CROP);
animatedImageView.setAnimDuration(1000); // default is 500
animatedImageView.setStartDelay(500);
animatedImageView.startAnimation;

动画 ImageView

/**
 * Custom ImageView that can animate ScaleType
 * Originally created by Wflei on 16/5/31.
 * Updated by Mike Miller (https://mikemiller.design) on 6/15/2017.
 * Original StackOverflow Post - https://stackoverflow.com/a/37539692/2415921
 */
public class AnimatedImageView extends android.support.v7.widget.AppCompatImageView {

    // Listener values;
    private ScaleType mFromScaleType, mToScaleType;
    private ValueAnimator mValueAnimator;
    private int mStartDelay = 0;
    private boolean isViewLayedOut = false;

    // Constructors
    public AnimatedImageView(Context context) {
        this(context, null);
    }

    public AnimatedImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AnimatedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // Set default original scale type
        mFromScaleType = getScaleType();

        // Set default scale type for animation
        mToScaleType = getScaleType();

        // Init value animator
        mValueAnimator = ValueAnimator.ofFloat(0f, 1f);

        // Set resource
        updateScaleType(mFromScaleType, false);
    }

    /**
     * Sets the scale type we want to animate to
     *
     * @param toScaleType
     */
    public void setAnimatedScaleType(ScaleType toScaleType) {
        mToScaleType = toScaleType;
    }

    /**
     * Duration of the animation
     *
     * @param animationDuration
     */
    public void setAnimDuration(int animationDuration) {
        mValueAnimator.setDuration(animationDuration);
    }

    /**
     * Set the time delayed for the animation
     *
     * @param startDelay The delay (in milliseconds) before the animation
     */
    public void setStartDelay(Integer startDelay) {
        mStartDelay = startDelay == null ? 0 : startDelay;
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        super.setScaleType(scaleType);
        mFromScaleType = scaleType;
    }

    @Override
    public void setImageDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
        updateScaleType(mFromScaleType, false);
    }

    @Override
    public void setImageBitmap(Bitmap bm) {
        super.setImageBitmap(bm);
        updateScaleType(mFromScaleType, false);
    }

    @Override
    public void setImageResource(int resId) {
        super.setImageResource(resId);
        updateScaleType(mFromScaleType, false);
    }

    @Override
    public void setImageURI(Uri uri) {
        super.setImageURI(uri);
        updateScaleType(mFromScaleType, false);
    }

    /**
     * Animates the current view
     * and updates it's current asset
     */
    public void startAnimation() {

        // This will run the animation with a delay (delay is defaulted at 0)
        postDelayed(startDelay, mStartDelay);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        // View has been laid out
        isViewLayedOut = true;

        // Animate change when bounds are official
        if (changed) {
            updateScaleType(mToScaleType, false);
        }
    }

    /**
     * animate to scaleType
     *
     * @param toScaleType
     */
    private void updateScaleType(final ScaleType toScaleType, boolean animated) {

        // Check if view is laid out
        if (!isViewLayedOut) {
            return;
        }

        // Cancel value animator if its running
        if (mValueAnimator != null && mValueAnimator.isRunning()) {
            mValueAnimator.cancel();
            mValueAnimator.removeAllUpdateListeners();
        }

        // Set the  scale type
        super.setScaleType(mFromScaleType);

        // Get values for the current image matrix
        setFrame(getLeft(), getTop(), getRight(), getBottom());
        Matrix srcMatrix = getImageMatrix();
        final float[] srcValues = new float[9], destValues = new float[9];
        srcMatrix.getValues(srcValues);

        // Set the scale type to the new type
        super.setScaleType(toScaleType);
        setFrame(getLeft(), getTop(), getRight(), getBottom());
        Matrix destMatrix = getImageMatrix();
        if (toScaleType == ScaleType.FIT_XY) {
            float sX = ((float) getWidth()) / getDrawable().getIntrinsicWidth();
            float sY = ((float) getHeight()) / getDrawable().getIntrinsicHeight();
            destMatrix.postScale(sX, sY);
        }
        destMatrix.getValues(destValues);

        // Get translation values
        final float transX = destValues[2] - srcValues[2];
        final float transY = destValues[5] - srcValues[5];
        final float scaleX = destValues[0] - srcValues[0];
        final float scaleY = destValues[4] - srcValues[4];

        // Set the scale type to a matrix
        super.setScaleType(ScaleType.MATRIX);

        // Listen to value animator changes
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = animation.getAnimatedFraction();
                float[] currValues = Arrays.copyOf(srcValues, srcValues.length);
                currValues[2] = srcValues[2] + transX * value;
                currValues[5] = srcValues[5] + transY * value;
                currValues[0] = srcValues[0] + scaleX * value;
                currValues[4] = srcValues[4] + scaleY * value;
                Matrix matrix = new Matrix();
                matrix.setValues(currValues);
                setImageMatrix(matrix);
            }
        });

        // Save the newly set scale type after animation completes
        mValueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

                // Set the from scale type to the newly used scale type
                mFromScaleType = toScaleType;
            }
        });

        // Start the animation
        if (animated) {
            mValueAnimator.start();
        } 
    }
}

关于android - 在 ImageView 中为 scaleType ="centerCrop"设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37535954/

相关文章:

android - 使用不匹配的驱动程序版本启用 glsl 扩展时崩溃

安卓 : Getting RuntimeException on AsyncTask

Android - 如何更改挂载点

android - 在上滑面板中旋转 ImageView

java - 如何共享所有应用程序 Activity 的对象

android - 实现google calendar imageviews "parallax"效果

android - 何时需要在 View 上执行 invalidate()?

java - 从 Activity 返回后保留 fragment

android - 如何改进我的动画并使其均匀(Jetpack Compose)?

带有叠加层的 Android 可缩放/可滚动 ImageView