android Activity转场动画makeSceneTransitionAnimation

1、activity转场动画实现有很多,这里主要记录ActivityOptions实现转场动画。

1、makeSceneTransitionAnimation实现,网上很多说要添加下面这句代码

<item name="android:windowContentTransitions">true</item>

或者Activity中添加requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);,但是实际不添加也可以

2、显示图片的那个ImageView要添加transitionName,两边显示的都要添加

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <com.example.mytestproject.view.ZoomImageView
        android:id="@+id/zoomImageView"
        android:layout_width="match_parent"
        android:src="@mipmap/item"
        android:transitionName="zoomImage"
        android:layout_height="match_parent"/>


</RelativeLayout>
3、跳转到的那个Activity要添加下面的属性
* changeBounds - 改变目标视图的布局边界
* changeClipBounds - 裁剪目标视图边界
* changeTransform - 改变目标视图的缩放比例和旋转角度
* changeImageTransform - 改变目标图片的大小和缩放比例
TransitionSet transitionSet = new TransitionSet();
            transitionSet.setOrdering(TransitionSet.ORDERING_TOGETHER);
            transitionSet.addTransition(new ChangeBounds());
            transitionSet.addTransition(new ChangeTransform());
            transitionSet.addTransition(new ChangeClipBounds());
            transitionSet.addTransition(new ChangeImageTransform());
            transitionSet.addTarget(mZoomImageView);
            getWindow().setSharedElementEnterTransition(transitionSet);
            getWindow().setSharedElementExitTransition(transitionSet);
            getWindow().setSharedElementsUseOverlay(true);

4、onBackPressed返回中添加

ActivityCompat.finishAfterTransition(this);

5、跳转动画实现,makeSceneTransitionAnimation实现,这个返回的时候也会有动画效果

ActivityOptions options = ActivityOptions
                            .makeSceneTransitionAnimation(RecyclerActivity.this,
                                    imageView, "zoomImage");
 Intent intent = new Intent(RecyclerActivity.this, ZoomActivity.class);
                startActivityForResult(intent, 1, options.toBundle());
makeScaleUpAnimation实现、这个是一个放大的效果
ActivityOptions options = ActivityOptions.makeScaleUpAnimation(imageView,
                            imageView.getWidth() / 2, imageView.getHeight() / 2, 0, 0);
Intent intent = new Intent(RecyclerActivity.this, ZoomActivity.class);
                startActivityForResult(intent, 1, options.toBundle());

还有下面几个动画效果,都可以看看

public static ActivityOptions makeClipRevealAnimation(View source, int startX, int startY, int width, int height)

public static ActivityOptions makeCustomAnimation(Context context, int enterResId, int exitResId)

public static ActivityOptions makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)

startActivity(new Intent(this, ZoomActivity.class), ActivityOptions.makeSceneTransitionAnimation (this, Pair.create(view, "myButton2"), Pair.create(view, "myButton3")) .toBundle());

6、最后给一个可以实现缩放移动等操作的图片显示View,有兴趣可以看看

package com.example.mytestproject.view;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

import androidx.appcompat.widget.AppCompatImageView;

/**
 * 保存图片点击的缩放类
 * create by xing
 * 2020/8
 */
public class ZoomImageView extends AppCompatImageView implements View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener {

    private final String TAG = "ZoomImageView";
    private Matrix mMatrix;
    private PointF mViewSize;
    private PointF mImageSize;
    private PointF mScaleSize;
    private PointF mCurPoint;
    private PointF mOriginScale;

    private ScaleGestureDetector mScaleGestureDetector = null;
    private GestureDetector mGestureDetector;
    private final float[] mMatrixValues = new float[9];
    private boolean isAutoScale;
    public static final float SCALE_MAX = 4.0f;
    private static final float SCALE_MID = 0.5f;
    private float mInitScale = 0.5f;
    private float mLastX;
    private float mLastY;

    private boolean isCanDrag;
    private int lastPointerCount;

    private boolean isCheckTopAndBottom = true;
    private boolean isCheckLeftAndRight = true;

    private float mDownX, mDownY = 0;
    private IGestureImageListener iGestureImageListener;

    public interface IGestureImageListener {
        void ZoomClick();
    }

    public void setGestureImageListener(IGestureImageListener listener) {
        this.iGestureImageListener = listener;
    }


    public ZoomImageView(Context context) {
        super(context);
        GestureImageViewInit(context);
    }

    public ZoomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        GestureImageViewInit(context);
    }

    public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        GestureImageViewInit(context);
    }

    public void GestureImageViewInit(Context context) {
        this.setOnTouchListener(this);
        this.setScaleType(ScaleType.MATRIX);
        mMatrix = new Matrix();
        mOriginScale = new PointF();
        mScaleSize = new PointF();
        mCurPoint = new PointF();
        mGestureDetector = new GestureDetector(context,
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        if (isAutoScale == true)
                            return true;

                        float x = e.getX();
                        float y = e.getY();

                        if (getScale() < SCALE_MID) {
                            ZoomImageView.this.postDelayed(new ZoomImageView.AutoScaleRunnable(SCALE_MID, x, y), 16);
                            isAutoScale = true;

                        } else if (getScale() >= SCALE_MID && getScale() < SCALE_MAX) {
                            ZoomImageView.this.postDelayed(new ZoomImageView.AutoScaleRunnable(SCALE_MAX, x, y), 16);
                            isAutoScale = true;

                        } else {
                            ZoomImageView.this.postDelayed(new ZoomImageView.AutoScaleRunnable(mInitScale, x, y), 16);
                            isAutoScale = true;
                        }

                        return true;
                    }
                });
        mScaleGestureDetector = new ScaleGestureDetector(context, this);
        this.setOnTouchListener(this);
    }

    private class AutoScaleRunnable implements Runnable {
        static final float BIGGER = 1.07f;
        static final float SMALLER = 0.43f;
        private float mTargetScale;
        private float tmpScale;
        private float x;
        private float y;

        public AutoScaleRunnable(float targetScale, float x, float y) {
            this.mTargetScale = targetScale;
            this.x = x;
            this.y = y;
            if (getScale() < mTargetScale) {
                tmpScale = SMALLER;
            } else {
                tmpScale = SMALLER;
            }

        }

        @Override
        public void run() {
            // 进行缩放
            mMatrix.postScale(tmpScale, tmpScale, x, y);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mMatrix);

            final float currentScale = getScale();

            if (((tmpScale > 1f) && (currentScale < mTargetScale))
                    || ((tmpScale < 1f) && (mTargetScale < currentScale))) {
                ZoomImageView.this.postDelayed(this, 16);
            } else {
                final float deltaScale = mTargetScale / currentScale;
                mMatrix.postScale(deltaScale, deltaScale, x, y);
                checkBorderAndCenterWhenScale();
                setImageMatrix(mMatrix);
                isAutoScale = false;
            }
        }
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float scale = getScale();
        float scaleFactor = detector.getScaleFactor();

        if (getDrawable() == null)
            return true;

        if ((scale < SCALE_MAX && scaleFactor > 1.0f)
                || (scale > mInitScale && scaleFactor < 1.0f)) {
            if (scaleFactor * scale < mInitScale) {
                scaleFactor = mInitScale / scale;
            }
            if (scaleFactor * scale > SCALE_MAX) {
                scaleFactor = SCALE_MAX / scale;
            }
            mMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
            checkBorderAndCenterWhenScale();
            setImageMatrix(mMatrix);
        }
        return true;
    }

    private RectF getMatrixRectF() {
        Matrix matrix1 = mMatrix;
        RectF rect = new RectF();
        Drawable d = getDrawable();
        if (null != d) {
            rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
            matrix1.mapRect(rect);
        }
        return rect;
    }

    private void checkBorderAndCenterWhenScale() {

        RectF rect = getMatrixRectF();
        float deltaX = 0;
        float deltaY = 0;

        int width = getWidth();
        int height = getHeight();

        // 如果宽或高大于屏幕,则控制范围
        if (rect.width() >= width) {
            if (rect.left > 0) {
                deltaX = -rect.left;
            }
            if (rect.right < width) {
                deltaX = width - rect.right;
            }
        }
        if (rect.height() >= height) {
            if (rect.top > 0) {
                deltaY = -rect.top;
            }
            if (rect.bottom < height) {
                deltaY = height - rect.bottom;
            }
        }
        if (rect.width() < width) {
            deltaX = width * 0.5f - rect.right + 0.5f * rect.width();
        }
        if (rect.height() < height) {
            deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();
        }

        mMatrix.postTranslate(deltaX, deltaY);

    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {

    }


    public final float getScale() {
        mMatrix.getValues(mMatrixValues);
        return mMatrixValues[Matrix.MSCALE_X];
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        mViewSize = new PointF(width, height);

        Drawable drawable = getDrawable();
        if (drawable == null) {
            Log.e(TAG, "drawable is nullPtr");
        } else {
            mImageSize = new PointF(drawable.getMinimumWidth(), drawable.getMinimumHeight());
        }

        fitCenter();
    }

    /**
     * 使图片保存在中央
     */
    public void fitCenter() {
        if (mViewSize != null && mImageSize != null) {
            float scaleH = mViewSize.y / mImageSize.y;
            float scaleW = mViewSize.x / mImageSize.x;
            float scale = scaleH < scaleW ? scaleH : scaleW;
            //根据view适应大小
            setImageScale(new PointF(scale, scale));

            mOriginScale.set(scale, scale);
            //根据缩放因子大小来将图片中心调整到view 中心
            if (scaleH < scaleW) {
                setImageTranslation(new PointF(mViewSize.x / 2 - mScaleSize.x / 2, 0));
            } else {
                setImageTranslation(new PointF(0, mViewSize.y / 2 - mScaleSize.y / 2));
            }

            //记录缩放因子 下次继续从这个比例缩放
            mInitScale = mOriginScale.x;
        }
    }




    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (mGestureDetector.onTouchEvent(event))
            return true;
        mScaleGestureDetector.onTouchEvent(event);

        float x = 0, y = 0;
        final int pointerCount = event.getPointerCount();
        for (int i = 0; i < pointerCount; i++) {
            x += event.getX(i);
            y += event.getY(i);
        }
        x = x / pointerCount;
        y = y / pointerCount;

        if (pointerCount != lastPointerCount) {
            isCanDrag = false;
            mLastX = x;
            mLastY = y;
        }

        lastPointerCount = pointerCount;
        RectF rectF = getMatrixRectF();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                mDownX = event.getX();
                mDownY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                float dx = x - mLastX;
                float dy = y - mLastY;

                if (!isCanDrag) {
                    isCanDrag = isCanDrag(dx, dy);
                }
                if (isCanDrag) {

                    if (getDrawable() != null) {
                        isCheckLeftAndRight = isCheckTopAndBottom = true;
                        if (rectF.width() < getWidth()) {
                            dx = 0;
                            isCheckLeftAndRight = false;
                        }
                        if (rectF.height() < getHeight()) {
                            dy = 0;
                            isCheckTopAndBottom = false;
                        }


                        mMatrix.postTranslate(dx, dy);
                        checkMatrixBounds();
                        setImageMatrix(mMatrix);
                    }
                }
                mLastX = x;
                mLastY = y;
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                float diffX = Math.abs(event.getX() - mDownX);
                float diffY = Math.abs(event.getY() - mDownY);
                if (diffX < 5 && diffY < 5) {
                    if (iGestureImageListener != null) {
                        iGestureImageListener.ZoomClick();
                    }
                }
                lastPointerCount = 0;
                break;
        }
        return true;
    }

    private void checkMatrixBounds() {
        RectF rect = getMatrixRectF();

        float deltaX = 0, deltaY = 0;
        final float viewWidth = getWidth();
        final float viewHeight = getHeight();
        // 判断移动或缩放后,图片显示是否超出屏幕边界
        if (rect.top > 0 && isCheckTopAndBottom) {
            deltaY = -rect.top;
        }
        if (rect.bottom < viewHeight && isCheckTopAndBottom) {
            deltaY = viewHeight - rect.bottom;
        }
        if (rect.left > 0 && isCheckLeftAndRight) {
            deltaX = -rect.left;
        }
        if (rect.right < viewWidth && isCheckLeftAndRight) {
            deltaX = viewWidth - rect.right;
        }
        mMatrix.postTranslate(deltaX, deltaY);
    }


    /**
     * 根据缩放因子缩放图片
     *
     * @param scale
     */
    public void setImageScale(PointF scale) {
        mMatrix.setScale(scale.x, scale.y);
        mScaleSize.set(scale.x * mImageSize.x, scale.y * mImageSize.y);
        this.setImageMatrix(mMatrix);
    }

    /**
     * 根据偏移量改变图片位置
     *
     * @param offset
     */
    public void setImageTranslation(PointF offset) {
        mMatrix.postTranslate(offset.x, offset.y);
        mCurPoint.set(offset);
        this.setImageMatrix(mMatrix);
    }

    private boolean isCanDrag(float dx, float dy) {
        return Math.sqrt((dx * dx) + (dy * dy)) >= 0;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值