Android多点触摸缩放图片

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

自定义ImageView

    package com.example.test;  
      
    import android.app.Activity;  
    import android.content.Context;  
    import android.graphics.Bitmap;  
    import android.graphics.Canvas;  
    import android.os.AsyncTask;  
    import android.text.method.MovementMethod;  
    import android.util.AttributeSet;  
    import android.util.FloatMath;  
    import android.util.Log;  
    import android.view.MotionEvent;  
    import android.view.animation.AccelerateInterpolator;  
    import android.view.animation.Animation;  
    import android.view.animation.Animation.AnimationListener;  
    import android.view.animation.ScaleAnimation;  
    import android.widget.ImageView;  
      
    /**** 
     * 这里你要明白几个方法执行的流程: 首先ImageView是继承自View的子类. 
     * onLayout方法:是一个回调方法.该方法会在在View中的layout方法中执行,在执行layout方法前面会首先执行setFrame方法. 
     * layout方法: 
     * setFrame方法:判断我们的View是否发生变化,如果发生变化,那么将最新的l,t,r,b传递给View,然后刷新进行动态更新UI. 
     * 并且返回ture.没有变化返回false. 
     *  
     * invalidate方法:用于刷新当前控件, 
     */  
    public class DragImageView extends ImageView {  
      
        private Activity mActivity;  
      
        private int screen_W, screen_H;// 可见屏幕的宽高度  
      
        private int bitmap_W, bitmap_H;// 当前图片宽高  
      
        private int MAX_W, MAX_H, MIN_W, MIN_H;// 极限值  
      
        private int current_Top, current_Right, current_Bottom, current_Left;// 当前图片上下左右坐标  
      
        private int start_Top = -1, start_Right = -1, start_Bottom = -1,  
                start_Left = -1;// 初始化默认位置.  
      
        private int start_x, start_y, current_x, current_y;// 触摸位置  
      
        private float beforeLenght, afterLenght;// 两触点距离  
      
        private float scale_temp;// 缩放比例  
      
        /** 
         * 模式 NONE:无 DRAG:拖拽. ZOOM:缩放 
         *  
         * @author zhangjia 
         *  
         */  
        private enum MODE {  
            NONE, DRAG, ZOOM  
      
        };  
      
        private MODE mode = MODE.NONE;// 默认模式  
      
        private boolean isControl_V = false;// 垂直监控  
      
        private boolean isControl_H = false;// 水平监控  
      
        private ScaleAnimation scaleAnimation;// 缩放动画  
      
        private boolean isScaleAnim = false;// 缩放动画  
      
        private MyAsyncTask myAsyncTask;// 异步动画  
      
        /** 构造方法 **/  
        public DragImageView(Context context) {  
            super(context);  
        }  
      
        public void setmActivity(Activity mActivity) {  
            this.mActivity = mActivity;  
        }  
      
        /** 可见屏幕宽度 **/  
        public void setScreen_W(int screen_W) {  
            this.screen_W = screen_W;  
        }  
      
        /** 可见屏幕高度 **/  
        public void setScreen_H(int screen_H) {  
            this.screen_H = screen_H;  
        }  
      
        public DragImageView(Context context, AttributeSet attrs) {  
            super(context, attrs);  
        }  
      
        /*** 
         * 设置显示图片 
         */  
        @Override  
        public void setImageBitmap(Bitmap bm) {  
            super.setImageBitmap(bm);  
            /** 获取图片宽高 **/  
            bitmap_W = bm.getWidth();  
            bitmap_H = bm.getHeight();  
      
            MAX_W = bitmap_W * 3;  
            MAX_H = bitmap_H * 3;  
      
            MIN_W = bitmap_W / 2;  
            MIN_H = bitmap_H / 2;  
      
        }  
      
        @Override  
        protected void onLayout(boolean changed, int left, int top, int right,  
                int bottom) {  
            super.onLayout(changed, left, top, right, bottom);  
            if (start_Top == -1) {  
                start_Top = top;  
                start_Left = left;  
                start_Bottom = bottom;  
                start_Right = right;  
            }  
      
        }  
      
        /*** 
         * touch 事件 
         */  
        @Override  
        public boolean onTouchEvent(MotionEvent event) {  
            /** 处理单点、多点触摸 **/  
            switch (event.getAction() & MotionEvent.ACTION_MASK) {  
            case MotionEvent.ACTION_DOWN:  
                onTouchDown(event);  
                break;  
            // 多点触摸  
            case MotionEvent.ACTION_POINTER_DOWN:  
                onPointerDown(event);  
                break;  
      
            case MotionEvent.ACTION_MOVE:  
                onTouchMove(event);  
                break;  
            case MotionEvent.ACTION_UP:  
                mode = MODE.NONE;  
                break;  
      
            // 多点松开  
            case MotionEvent.ACTION_POINTER_UP:  
                mode = MODE.NONE;  
                /** 执行缩放还原 **/  
                if (isScaleAnim) {  
                    doScaleAnim();  
                }  
                break;  
            }  
      
            return true;  
        }  
      
        /** 按下 **/  
        void onTouchDown(MotionEvent event) {  
            mode = MODE.DRAG;  
      
            current_x = (int) event.getRawX();  
            current_y = (int) event.getRawY();  
      
            start_x = (int) event.getX();  
            start_y = current_y - this.getTop();  
      
        }  
      
        /** 两个手指 只能放大缩小 **/  
        void onPointerDown(MotionEvent event) {  
            if (event.getPointerCount() == 2) {  
                mode = MODE.ZOOM;  
                beforeLenght = getDistance(event);// 获取两点的距离  
            }  
        }  
      
        /** 移动的处理 **/  
        void onTouchMove(MotionEvent event) {  
            int left = 0, top = 0, right = 0, bottom = 0;  
            /** 处理拖动 **/  
            if (mode == MODE.DRAG) {  
      
                /** 在这里要进行判断处理,防止在drag时候越界 **/  
      
                /** 获取相应的l,t,r ,b **/  
                left = current_x - start_x;  
                right = current_x + this.getWidth() - start_x;  
                top = current_y - start_y;  
                bottom = current_y - start_y + this.getHeight();  
      
                /** 水平进行判断 **/  
                if (isControl_H) {  
                    if (left >= 0) {  
                        left = 0;  
                        right = this.getWidth();  
                    }  
                    if (right <= screen_W) {  
                        left = screen_W - this.getWidth();  
                        right = screen_W;  
                    }  
                } else {  
                    left = this.getLeft();  
                    right = this.getRight();  
                }  
                /** 垂直判断 **/  
                if (isControl_V) {  
                    if (top >= 0) {  
                        top = 0;  
                        bottom = this.getHeight();  
                    }  
      
                    if (bottom <= screen_H) {  
                        top = screen_H - this.getHeight();  
                        bottom = screen_H;  
                    }  
                } else {  
                    top = this.getTop();  
                    bottom = this.getBottom();  
                }  
                if (isControl_H || isControl_V)  
                    this.setPosition(left, top, right, bottom);  
      
                current_x = (int) event.getRawX();  
                current_y = (int) event.getRawY();  
      
            }  
            /** 处理缩放 **/  
            else if (mode == MODE.ZOOM) {  
                afterLenght = getDistance(event);// 获取两点的距离  
                float gapLenght = afterLenght - beforeLenght;// 变化的长度  
                if (Math.abs(gapLenght) > 5f) {  
                    scale_temp = afterLenght / beforeLenght;// 求的缩放的比例  
                    this.setScale(scale_temp);  
                    beforeLenght = afterLenght;  
                }  
            }  
        }  
      
        /** 获取两点的距离 **/  
        float getDistance(MotionEvent event) {  
            float x = event.getX(0) - event.getX(1);  
            float y = event.getY(0) - event.getY(1);  
            return FloatMath.sqrt(x * x + y * y);  
        }  
      
        /** 实现处理拖动 **/  
        private void setPosition(int left, int top, int right, int bottom) {  
            this.layout(left, top, right, bottom);  
        }  
      
        /** 处理缩放 **/  
        void setScale(float scale) {  
            int disX = (int) (this.getWidth() * Math.abs(1 - scale)) / 4;// 获取缩放水平距离  
            int disY = (int) (this.getHeight() * Math.abs(1 - scale)) / 4;// 获取缩放垂直距离  
      
            // 放大  
            if (scale > 1 && this.getWidth() <= MAX_W) {  
                current_Left = this.getLeft() - disX;  
                current_Top = this.getTop() - disY;  
                current_Right = this.getRight() + disX;  
                current_Bottom = this.getBottom() + disY;  
                this.setFrame(current_Left, current_Top, current_Right,  
                        current_Bottom);  
                /*** 
                 * 此时因为考虑到对称,所以只做一遍判断就可以了。 
                 */  
                if (current_Top <= 0 && current_Bottom >= screen_H) {  
            //      Log.e("jj", "屏幕高度=" + this.getHeight());  
                    isControl_V = true;// 开启垂直监控  
                } else {  
                    isControl_V = false;  
                }  
                if (current_Left <= 0 && current_Right >= screen_W) {  
                    isControl_H = true;// 开启水平监控  
                } else {  
                    isControl_H = false;  
                }  
            }  
            // 缩小  
            else if (scale < 1 && this.getWidth() >= MIN_W) {  
                current_Left = this.getLeft() + disX;  
                current_Top = this.getTop() + disY;  
                current_Right = this.getRight() - disX;  
                current_Bottom = this.getBottom() - disY;  
                /*** 
                 * 在这里要进行缩放处理 
                 */  
                // 上边越界  
                if (isControl_V && current_Top > 0) {  
                    current_Top = 0;  
                    current_Bottom = this.getBottom() - 2 * disY;  
                    if (current_Bottom < screen_H) {  
                        current_Bottom = screen_H;  
                        isControl_V = false;// 关闭垂直监听  
                    }  
                }  
                // 下边越界  
                if (isControl_V && current_Bottom < screen_H) {  
                    current_Bottom = screen_H;  
                    current_Top = this.getTop() + 2 * disY;  
                    if (current_Top > 0) {  
                        current_Top = 0;  
                        isControl_V = false;// 关闭垂直监听  
                    }  
                }  
                // 左边越界  
                if (isControl_H && current_Left >= 0) {  
                    current_Left = 0;  
                    current_Right = this.getRight() - 2 * disX;  
                    if (current_Right <= screen_W) {  
                        current_Right = screen_W;  
                        isControl_H = false;// 关闭  
                    }  
                }  
                // 右边越界  
                if (isControl_H && current_Right <= screen_W) {  
                    current_Right = screen_W;  
                    current_Left = this.getLeft() + 2 * disX;  
                    if (current_Left >= 0) {  
                        current_Left = 0;  
                        isControl_H = false;// 关闭  
                    }  
                }  
                if (isControl_H || isControl_V) {  
                    this.setFrame(current_Left, current_Top, current_Right,  
                            current_Bottom);  
                } else {  
                    this.setFrame(current_Left, current_Top, current_Right,  
                            current_Bottom);  
                    isScaleAnim = true;// 开启缩放动画  
                }  
            }  
        }  
      
        /*** 
         * 缩放动画处理 
         */  
        public void doScaleAnim() {  
            myAsyncTask = new MyAsyncTask(screen_W, this.getWidth(),  
                    this.getHeight());  
            myAsyncTask.setLTRB(this.getLeft(), this.getTop(), this.getRight(),  
                    this.getBottom());  
            myAsyncTask.execute();  
            isScaleAnim = false;// 关闭动画  
        }  
      
        /*** 
         * 回缩动画執行 
         */  
        class MyAsyncTask extends AsyncTask<Void, Integer, Void> {  
            private int screen_W, current_Width, current_Height;  
      
            private int left, top, right, bottom;  
      
            private float scale_WH;// 宽高的比例  
      
            /** 当前的位置属性 **/  
            public void setLTRB(int left, int top, int right, int bottom) {  
                this.left = left;  
                this.top = top;  
                this.right = right;  
                this.bottom = bottom;  
            }  
      
            private float STEP = 8f;// 步伐  
            private float step_H, step_V;// 水平步伐,垂直步伐  
            public MyAsyncTask(int screen_W, int current_Width, int current_Height) {  
                super();  
                this.screen_W = screen_W;  
                this.current_Width = current_Width;  
                this.current_Height = current_Height;  
                scale_WH = (float) current_Height / current_Width;  
                step_H = STEP;  
                step_V = scale_WH * STEP;  
            }  
      
            @Override  
            protected Void doInBackground(Void... params) {  
                while (current_Width <= screen_W) {  
                    left -= step_H;  
                    top -= step_V;  
                    right += step_H;  
                    bottom += step_V;  
      
                    current_Width += 2 * step_H;  
      
                    left = Math.max(left, start_Left);  
                    top = Math.max(top, start_Top);  
                    right = Math.min(right, start_Right);  
                    bottom = Math.min(bottom, start_Bottom);  
                    Log.e("jj", "top="+top+",bottom="+bottom+",left="+left+",right="+right);  
                    onProgressUpdate(new Integer[] { left, top, right, bottom });  
                    try {  
                        Thread.sleep(10);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                }  
                return null;  
            }  
      
            @Override  
            protected void onProgressUpdate(final Integer... values) {  
                super.onProgressUpdate(values);  
                mActivity.runOnUiThread(new Runnable() {  
                    @Override  
                    public void run() {  
                        setFrame(values[0], values[1], values[2], values[3]);  
                    }  
                });  
            }  
        }  
    }  

执行调用Activity

    package com.example.test;  
      
    import android.app.Activity;  
    import android.graphics.Bitmap;  
    import android.graphics.BitmapFactory;  
    import android.graphics.Rect;  
    import android.os.Bundle;  
    import android.util.DisplayMetrics;  
    import android.view.ViewTreeObserver;  
    import android.view.Window;  
    import android.view.WindowManager;  
    import android.view.ViewTreeObserver.OnGlobalLayoutListener;  
    import android.widget.ImageView;  
      
    public class Test extends Activity {  
      
        private int state_height;  
        private int screenWidth;  
        private int screenHeight;  
        private ViewTreeObserver viewTreeObserver;  
        private DragImageView dragImageView;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            requestWindowFeature(Window.FEATURE_NO_TITLE);  
            setContentView(R.layout.test);  
            dragImageView = (DragImageView) findViewById(R.id.img);  
            //获取屏幕宽高  
            DisplayMetrics dm = new DisplayMetrics();  
            getWindowManager().getDefaultDisplay().getMetrics(dm);  
            screenWidth = dm.widthPixels;  
            screenHeight = dm.heightPixels;  
            //读取图片并且按宽度比例压缩  
            Bitmap bitmap = BitmapUtil.ReadBitmapById(this, R.drawable.ke,screenWidth, screenHeight);  
            dragImageView.setImageBitmap(bitmap);  
            // 传入Activity以更新缩放画面  
            dragImageView.setmActivity(this);  
            /** 测量状态栏高度 **/  
            viewTreeObserver = dragImageView.getViewTreeObserver();  
            viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {  
      
                    @Override  
                    public void onGlobalLayout() {  
                        if (state_height == 0) {  
                            // 获取状态栏高度  
                            Rect frame = new Rect();  
                            getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
                            state_height = frame.top;  
                            //去掉状态栏高度  
                            dragImageView.setScreen_H(screenHeight- state_height);  
                            dragImageView.setScreen_W(screenWidth);  
                        }  
                    }  
            });  
        }  
    }