Android多点触控技术,实现对图片的放大缩小平移,惯性滑动等功能

首先推荐一下鸿洋大大的打造个性的图片预览与多点触控视频教程,这套教程教我们一步一步实现了多点触控实现对图片的平移和缩放的功能,这篇文章我将在鸿洋大大的基础之上做了一些扩展功能:
1.图片的惯性滑动
2.图片缩放小于正常比例时,松手会自动回弹成正常比例
3.图片缩放大于最大比例时,松手会自动回弹成最大比例

这里写图片描述

实现图片的缩放,平移,双击缩放等基本功能的代码如下,每一行代码我都做了详细的注释

public class ZoomImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener,
        View.OnTouchListener , ViewTreeObserver.OnGlobalLayoutListener{
   
    /**
     * 缩放手势的监测
     */
    private ScaleGestureDetector mScaleGestureDetector;
    /**
     * 监听手势
     */
    private GestureDetector mGestureDetector;
    /**
     * 对图片进行缩放平移的Matrix
     */
    private Matrix mScaleMatrix;
    /**
     * 第一次加载图片时调整图片缩放比例,使图片的宽或者高充满屏幕
     */
    private boolean mFirst;
    /**
     * 图片的初始化比例
     */
    private float mInitScale;
    /**
     * 图片的最大比例
     */
    private float mMaxScale;
    /**
     * 双击图片放大的比例
     */
    private float mMidScale;

    /**
     * 是否正在自动放大或者缩小
     */
    private boolean isAutoScale;

    //-----------------------------------------------
    /**
     * 上一次触控点的数量
     */
    private int mLastPointerCount;
    /**
     * 是否可以拖动
     */
    private boolean isCanDrag;
    /**
     * 上一次滑动的x和y坐标
     */
    private float mLastX;
    private float mLastY;
    /**
     * 可滑动的临界值
     */
    private int mTouchSlop;
    /**
     * 是否用检查左右边界
     */
    private boolean isCheckLeftAndRight;
    /**
     * 是否用检查上下边界
     */
    private boolean isCheckTopAndBottom;


    public ZoomImageView(Context context) {
        this(context, null, 0);
    }

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

    public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //一定要将图片的ScaleType设置成Matrix类型的
        setScaleType(ScaleType.MATRIX);
        //初始化缩放手势监听器
        mScaleGestureDetector = new ScaleGestureDetector(context,this);
        //初始化矩阵
        mScaleMatrix = new Matrix();
        setOnTouchListener(this);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        //初始化手势检测器,监听双击事件
        mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                //如果是正在自动缩放,则直接返回,不进行处理
                if (isAutoScale) return true;
                //得到点击的坐标
                float x = e.getX();
                float y = e.getY();
                //如果当前图片的缩放值小于指定的双击缩放值
                if (getScale() < mMidScale){
                    //进行自动放大
                    post(new AutoScaleRunnable(mMidScale,x,y));
                }else{
                    //当前图片的缩放值大于初试缩放值,则自动缩小
                    post(new AutoScaleRunnable(mInitScale,x,y));
                }
                return true;
            }
        });



    }

    /**
     * 当view添加到window时调用,早于onGlobalLayout,因此可以在这里注册监听器
     */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    /**
     * 当view从window上移除时调用,因此可以在这里移除监听器
     */
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    /**
     * 当布局树发生变化时会调用此方法,我们可以在此方法中获得控件的宽和高
     */
    @Override
    public void onGlobalLayout() {
        //只有当第一次加载图片的时候才会进行初始化,用一个变量mFirst控制
        if (!mFirst){
            mFirst = true;
            //得到控件的宽和高
            int width = getWidth();
            int height = getHeight();
            //得到当前ImageView中加载的图片
            Drawable d = getDrawable();
            if(d == null){
  //如果没有图片,则直接返回
                return;
            }
            //得到当前图片的宽和高,图片的宽和高不一定等于控件的宽和高
            //因此我们需要将图片的宽和高与控件宽和高进行判断
            //将图片完整的显示在屏幕中
            int dw = d.getIntrinsicWidth();
            int dh = d.getIntrinsicHeight();
            //我们定义一个临时变量,根据图片与控件的宽高比例,来确定这个最终缩放值
            float scale = 1.0f;
            //如果图片宽度大于控件宽度,图片高度小于控件高度
            if (dw>width && dh<height){
                //我们需要将图片宽度缩小,缩小至控件的宽度
                //至于为什么要这样计算,我们可以这样想
                //我们调用matrix.postScale(scale,scale)时,宽和高都要乘以scale的
                //当前我们的图片宽度是dw,dw*scale=dw*(width/dw)=width,这样就等于控件宽度了
                //我们的高度同时也乘以scale,这样能够保证图片的宽高比不改变,图片不变形
                scale = width * 1.0f / dw;

            }
            //如果图片的宽度小于控件宽度,图片高度大于控件高度
            if (dw<width && dh>height){
                //我们就应该将图片的高度缩小,缩小至控件的高度,计算方法同上
                scale 
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值