animate scaleType=“centerCrop” in ImageView

2019-07-12 19:55发布

Is there a way to animate scaleType="centerCrop"? I need to scale my image to certerCrop so the image can cover the entire area of the imageView. But I need to animate it to show the user the actual look of the image before it is being scaled I was planning to do it this way

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

but the problem is that I will be doing this on multiple image for a slide show so each image will have a different size and orientation.

I also found this library https://github.com/flavioarfaria/KenBurnsView but still having problems using it.

Any help will be much appreciated thanks.

EDITED

Started working on the KenBurnsView still not able to pan the image to center.

1条回答
闹够了就滚
2楼-- · 2019-07-12 20:20

I wrote a custom ImageView to support animation between ScaleTypes, Hope it is helpful for you. And forgive my bad English, It is not my first language.

Usage:

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;

AnimatedImageView

/**
 * Custom ImageView that can animate ScaleType
 * Originally created by Wflei on 16/5/31.
 * Updated by Mike Miller (http://www.mikemilla.com) 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();
        } 
    }
}
查看更多
登录 后发表回答