View的拖拽和缩放

来源:互联网 发布:网络防雷保护器 编辑:程序博客网 时间:2024/06/05 18:36
[java] view plaincopy
  1. package com.demo.pinch;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.util.FloatMath;  
  6. import android.view.MotionEvent;  
  7. import android.view.animation.AccelerateInterpolator;  
  8. import android.view.animation.Animation;  
  9. import android.view.animation.Animation.AnimationListener;  
  10. import android.view.animation.ScaleAnimation;  
  11. import android.view.animation.TranslateAnimation;  
  12. import android.widget.ImageView;  
  13.   
  14. /** 
  15.  * ImageView Tonuch 
  16.  *  
  17.  * @author Laladin.SYD 
  18.  *  
  19.  */  
  20. public class PinchableImageView extends ImageView {  
  21.     static final int NONE = 0;  
  22.     // 拖动中  
  23.     static final int DRAG = 1;  
  24.     // 缩放中  
  25.     static final int ZOOM = 2;  
  26.     // 放大ing  
  27.     static final int BIGGER = 3;  
  28.     // 缩小ing  
  29.     static final int SMALLER = 4;  
  30.     // 关闭缩放动画  
  31.     static final int OPENSCALE = 1;  
  32.     // 关闭移动动画  
  33.     static final int OPENTRANS = 2;  
  34.     // 当前的事件  
  35.     private int mode = NONE;  
  36.     // 两触点距离  
  37.     private float beforeLenght;  
  38.     // 两触点距离  
  39.     private float afterLenght;  
  40.     // 缩放的比例 X Y方向都是这个值 越大缩放的越快  
  41.     private float scale = 0.06f;  
  42.     /* 处理拖动 变量 */  
  43.     private int screenW;  
  44.     private int screenH;  
  45.     private int start_x;  
  46.     private int start_y;  
  47.     private int stop_x;  
  48.     private int stop_y;  
  49.     private TranslateAnimation trans;  
  50.     /* Bitmap的宽高 */  
  51.     private int bmWidth;  
  52.     private int bmHeight;  
  53.     // 处理超出边界的动画  
  54.     private Bitmap bitmap;  
  55.     private float maxScale = 2.0f;  
  56.     private float minScale = 1.0f;  
  57.     // 记录初始宽度,用于缩放回弹  
  58.     private int startWidth = 0;  
  59.     private float piovtX = 0.5f;  
  60.     private float piovtY = 0.5f;  
  61.     // 默认开启所有动画  
  62.     private int AnimSwitch = OPENSCALE | OPENTRANS;  
  63.   
  64.     /** 
  65.      * 构造函数 
  66.      *  
  67.      * @param context 
  68.      *            相关上下文 
  69.      * @param w 
  70.      *            容器的宽 
  71.      * @param h 
  72.      *            容器的高 
  73.      */  
  74.     public PinchableImageView(Context context, int w, int h) {  
  75.         super(context);  
  76.         this.setPadding(0000);  
  77.         screenW = w;  
  78.         screenH = h;  
  79.     }  
  80.   
  81.     @Override  
  82.     public void setImageBitmap(Bitmap bm) {  
  83.         super.setImageBitmap(bm);  
  84.         // 重置startWidth  
  85.         startWidth = 0;  
  86.         bmWidth = bm.getWidth();  
  87.         bmHeight = bm.getHeight();  
  88.         if (bitmap != null && !bitmap.isRecycled())  
  89.             bitmap.recycle();  
  90.         bitmap = bm;  
  91.     }  
  92.   
  93.     /** 
  94.      * 释放ImageView的Bitmap 
  95.      */  
  96.     public void recycle() {  
  97.         setImageBitmap(null);  
  98.         if (bitmap != null && !bitmap.isRecycled())  
  99.             bitmap.recycle();  
  100.     }  
  101.   
  102.     /** 
  103.      * 计算两点间的距离 
  104.      */  
  105.     private float spacing(MotionEvent event) {  
  106.         float x = event.getX(0) - event.getX(1);  
  107.         float y = event.getY(0) - event.getY(1);  
  108.         return FloatMath.sqrt(x * x + y * y);  
  109.     }  
  110.   
  111.     private float[] center;  
  112.   
  113.     /** 
  114.      * 计算两点间的中心点 
  115.      */  
  116.     private float[] centerPostion(MotionEvent event) {  
  117.         float[] center = new float[2];  
  118.         float x = event.getX(0);  
  119.         float y = event.getY(0);  
  120.         float x1 = event.getX(1);  
  121.         float y1 = event.getY(1);  
  122.         /* x,y分别的距离 */  
  123.         center[0] = Math.abs((x1 - x) / 2);  
  124.         center[1] = Math.abs((y1 - y) / 2);  
  125.         center[0] = Math.max(x, x1) - center[0];  
  126.         center[1] = Math.max(y, y1) - center[1];  
  127.         return center;  
  128.     }  
  129.   
  130.     /** 
  131.      * 设置ImageView大小等于显示的内容大小 
  132.      */  
  133.     public void setRect() {  
  134.         float scale = Math.min((float) getWidth() / (float) bmWidth,  
  135.                 (float) getHeight() / (float) bmHeight);  
  136.         int w = (int) ((float) bmWidth * scale) + 1;  
  137.         int h = (int) ((float) bmHeight * scale) + 1;  
  138.         // int t=(screenH-h)/2;  
  139.         // int l=(screenW-w)/2;  
  140.         int t = getTop();  
  141.         int l = getLeft();  
  142.         layout(l, t, l + w, t + h);  
  143.     }  
  144.   
  145.     /** 
  146.      * 处理各种移动回弹 
  147.      *  
  148.      * @param disX 
  149.      *            X的偏移 
  150.      * @param disY 
  151.      *            Y的偏移 
  152.      */  
  153.     public void Rebound(int disX, int disY) {  
  154.         this.layout(getLeft() + disX, getTop() + disY, getLeft() + disX  
  155.                 + getWidth(), getTop() + disY + getHeight());  
  156.         if ((AnimSwitch & OPENTRANS) == 0)  
  157.             return;  
  158.         trans = new TranslateAnimation(-disX, 0, -disY, 0);  
  159.         trans.setInterpolator(new AccelerateInterpolator());  
  160.         trans.setDuration(300);  
  161.         this.startAnimation(trans);  
  162.     }  
  163.   
  164.     /** 
  165.      * 处理各种缩放回弹 
  166.      */  
  167.     public boolean ReScale() {  
  168.         float scaleX = 1f;  
  169.         float scaleY = 1f;  
  170.         int width = getWidth();  
  171.         int height = getHeight();  
  172.         int l, t, r, b;  
  173.         if (center == null)  
  174.             return false;  
  175.         if (getWidth() > startWidth * maxScale) {  
  176.             while (getWidth() > startWidth * maxScale) {  
  177.                 l = this.getLeft() + (int) (center[0] * this.getWidth());  
  178.                 t = this.getTop() + (int) (center[1] * this.getHeight());  
  179.                 r = this.getRight()  
  180.                         - (int) ((scale - center[0]) * this.getWidth());  
  181.                 b = this.getBottom()  
  182.                         - (int) ((scale - center[1]) * this.getHeight());  
  183.                 this.setFrame(l, t, r, b);  
  184.             }  
  185.             scaleX = (float) width / (float) getWidth();  
  186.             scaleY = (float) height / (float) getHeight();  
  187.         }  
  188.         if (getWidth() < startWidth * minScale) {  
  189.             while (getWidth() < startWidth * minScale) {  
  190.                 l = this.getLeft() - (int) (center[0] * this.getWidth());  
  191.                 t = this.getTop() - (int) (center[1] * this.getHeight());  
  192.                 r = this.getRight()  
  193.                         + (int) ((scale - center[0]) * this.getWidth());  
  194.                 b = this.getBottom()  
  195.                         + (int) ((scale - center[1]) * this.getHeight());  
  196.                 this.setFrame(l, t, r, b);  
  197.             }  
  198.             scaleX = (float) width / (float) getWidth();  
  199.             scaleY = (float) height / (float) getHeight();  
  200.         }  
  201.   
  202.         if (scaleX == 1f && scaleY == 1f)  
  203.             return false;  
  204.         if ((AnimSwitch & OPENSCALE) == 0) {  
  205.             setRect();  
  206.             onRebound();  
  207.             return true;  
  208.         }  
  209.         ScaleAnimation scaleanim = new ScaleAnimation(scaleX, 1f, scaleY, 1f,  
  210.                 ScaleAnimation.RELATIVE_TO_SELF, piovtX,  
  211.                 ScaleAnimation.RELATIVE_TO_SELF, piovtY);  
  212.         scaleanim.setDuration(300);  
  213.         scaleanim.setInterpolator(new AccelerateInterpolator());  
  214.         scaleanim.setAnimationListener(new AnimationListener() {  
  215.             @Override  
  216.             public void onAnimationStart(Animation paramAnimation) {  
  217.             }  
  218.   
  219.             @Override  
  220.             public void onAnimationRepeat(Animation paramAnimation) {  
  221.             }  
  222.   
  223.             @Override  
  224.             public void onAnimationEnd(Animation paramAnimation) {  
  225.                 setRect();  
  226.                 onRebound();  
  227.             }  
  228.   
  229.         });  
  230.         this.startAnimation(scaleanim);  
  231.         return true;  
  232.     }  
  233.   
  234.     /** 
  235.      * 处理超范围回弹 
  236.      */  
  237.     private void onRebound() {  
  238.         /* 判断是否超出范围 并处理 */  
  239.         int disX = 0, disY = 0;  
  240.         if (getHeight() < screenH) {  
  241.             disY = (screenH - getHeight()) / 2 - getTop();  
  242.         }  
  243.         if (getWidth() < screenW) {  
  244.             disX = (screenW - getWidth()) / 2 - getLeft();  
  245.         }  
  246.         if (getHeight() >= screenH) {  
  247.             if (getTop() > 0)  
  248.                 disY = -getTop();  
  249.             if (getBottom() < screenH)  
  250.                 disY = screenH - getBottom();  
  251.         }  
  252.         if (getWidth() >= screenW) {  
  253.             if (getLeft() > 0)  
  254.                 disX = -getLeft();  
  255.             if (getRight() < screenW)  
  256.                 disX = screenW - getRight();  
  257.         }  
  258.         // 开始回弹  
  259.         Rebound(disX, disY);  
  260.     }  
  261.   
  262.     @Override  
  263.     protected void onLayout(boolean changed, int left, int top, int right,  
  264.             int bottom) {  
  265.         // TODO Auto-generated method stub  
  266.         super.onLayout(changed, left, top, right, bottom);  
  267.         if (startWidth == 0) {  
  268.             startWidth = right - left;  
  269.             setRect();  
  270.             AnimSwitch = 0;  
  271.             onRebound();  
  272.             AnimSwitch = OPENSCALE | OPENTRANS;  
  273.         }  
  274.     }  
  275.   
  276.     /** 
  277.      * 处理触碰.. 
  278.      */  
  279.     @Override  
  280.     public boolean onTouchEvent(MotionEvent event) {  
  281.         switch (event.getAction() & MotionEvent.ACTION_MASK) {  
  282.         case MotionEvent.ACTION_DOWN:  
  283.             mode = DRAG;  
  284.             stop_x = (int) event.getRawX();  
  285.             stop_y = (int) event.getRawY();  
  286.             start_x = (int) event.getX();  
  287.             start_y = stop_y - this.getTop();  
  288.             if (event.getPointerCount() == 2)  
  289.                 beforeLenght = spacing(event);  
  290.             break;  
  291.         case MotionEvent.ACTION_POINTER_DOWN:  
  292.             /** 下面三句用于计算缩放中心点位置 **/  
  293.             center = centerPostion(event);  
  294.             piovtX = center[0] / getWidth();  
  295.             piovtY = center[1] / getHeight();  
  296.   
  297.             center[0] = (center[0] / getWidth()) * scale;  
  298.             center[1] = (center[1] / getHeight()) * scale;  
  299.             if (spacing(event) > 10f) {  
  300.                 mode = ZOOM;  
  301.                 beforeLenght = spacing(event);  
  302.             }  
  303.             break;  
  304.         case MotionEvent.ACTION_UP:  
  305.             mode = NONE;  
  306.             //setRect();  
  307.             /* 判断是否超过缩放界限 */  
  308.             //if (!ReScale())  
  309.             //  onRebound();  
  310.             break;  
  311.         case MotionEvent.ACTION_POINTER_UP:  
  312.             mode = NONE;  
  313.             break;  
  314.         case MotionEvent.ACTION_MOVE:  
  315.             /* 处理拖动 */  
  316.             if (mode == DRAG) {  
  317.                 this.setPosition(stop_x - start_x, stop_y - start_y, stop_x  
  318.                         + this.getWidth() - start_x,  
  319.                         stop_y - start_y + this.getHeight());  
  320.                 stop_x = (int) event.getRawX();  
  321.                 stop_y = (int) event.getRawY();  
  322.             }  
  323.             /* 处理缩放 */  
  324.             else if (mode == ZOOM) {  
  325.                 if (spacing(event) > 10f) {  
  326.                     afterLenght = spacing(event);  
  327.                     float gapLenght = afterLenght - beforeLenght;  
  328.                     if (gapLenght == 0) {  
  329.                         break;  
  330.                     } else if (Math.abs(gapLenght) > 5f) {  
  331.                         if (gapLenght > 0) {  
  332.                             this.setScale(scale, BIGGER);  
  333.                         } else {  
  334.                             this.setScale(scale, SMALLER);  
  335.                         }  
  336.                         beforeLenght = afterLenght;  
  337.                     }  
  338.                 }  
  339.             }  
  340.             break;  
  341.         }  
  342.         return true;  
  343.     }  
  344.   
  345.     /** 
  346.      * 实现处理缩放 
  347.      */  
  348.     private void setScale(float temp, int flag) {  
  349.         int l = 0, t = 0, r = 0, b = 0;  
  350.         if (flag == BIGGER) {  
  351.             l = this.getLeft() - (int) (center[0] * this.getWidth());  
  352.             t = this.getTop() - (int) (center[1] * this.getHeight());  
  353.             r = this.getRight() + (int) ((scale - center[0]) * this.getWidth());  
  354.             b = this.getBottom()  
  355.                     + (int) ((scale - center[1]) * this.getHeight());  
  356.         } else if (flag == SMALLER) {  
  357.             l = this.getLeft() + (int) (center[0] * this.getWidth());  
  358.             t = this.getTop() + (int) (center[1] * this.getHeight());  
  359.             r = this.getRight() - (int) ((scale - center[0]) * this.getWidth());  
  360.             b = this.getBottom()  
  361.                     - (int) ((scale - center[1]) * this.getHeight());  
  362.         }  
  363.         this.setFrame(l, t, r, b);  
  364.     }  
  365.   
  366.     /** 
  367.      * 实现处理拖动 
  368.      */  
  369.     private void setPosition(int left, int top, int right, int bottom) {  
  370.         this.layout(left, top, right, bottom);  
  371.     }  
  372. }  
0 0