Android实现ImageView图片双击放大及缩小

转载自:http://www.jb51.net/article/79599.htm
public class DoubleScaleImageView extends ImageView implements OnTouchListener, OnGlobalLayoutListener {
   private boolean isFirst = false ;
   private float doubleScale; // 双击放大的值
   private Matrix mScaleMatrix;
   private float defaultScale; // 默认的缩放值
   private int mLastPinterCount; // 记录上一次多点触控的数量
   private float mLastX;
   private float mLastY;
   private int mTouchSlop;
   private boolean isCanDrag;
   private boolean isCheckLeft;
   private boolean isCheckTop;
   private GestureDetector mGestureDetector;
   public DoubleScaleImageView(Context context) {
     this (context, null );
   }
   public DoubleScaleImageView(Context context, AttributeSet attrs) {
     this (context, attrs, 0 );
   }
   @SuppressLint ( "ClickableViewAccessibility" )
   public DoubleScaleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
     super (context, attrs, defStyleAttr);
     mScaleMatrix = new Matrix();
     setScaleType(ScaleType.MATRIX);
     setOnTouchListener( this );
     // getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件。如果小于这个距离就不触发移动控件
     mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
       @Override
       public boolean onDoubleTap(MotionEvent e) {
         float x = e.getX();
         float y = e.getY();
         if (getScale() < doubleScale) {
           mScaleMatrix.postScale(doubleScale / getScale(), doubleScale / getScale(), x, y); // 放大
         }
         else {
           mScaleMatrix.postScale(defaultScale / getScale(), defaultScale / getScale(), x, y); // 缩小
         }
         setImageMatrix(mScaleMatrix);
         return super .onDoubleTap(e);
       }
     });
   }
   @Override
   protected void onAttachedToWindow() { // view附加到窗体上时调用该方法
     super .onAttachedToWindow();
     getViewTreeObserver().addOnGlobalLayoutListener( this );
   }
   @SuppressWarnings ( "deprecation" )
   @Override
   protected void onDetachedFromWindow() { // 将视图从窗体上分离的时候调用该方法。
     super .onDetachedFromWindow();
     getViewTreeObserver().removeGlobalOnLayoutListener( this );
   }
   @Override
   public void onGlobalLayout() { // 在这个方法中获取ImageView加载完成后的图片
     if (!isFirst) {
       // 获取控件的宽度和高度
       int width = getWidth();
       int height = getHeight();
       // 得到我们的图片以及图片的宽度及高度
       Drawable drawable = getDrawable();
       if (drawable == null ) { return ; }
       int imageWidth = drawable.getIntrinsicWidth(); // 图片的宽度
       int imageHeight = drawable.getIntrinsicHeight(); // 图片的高度
       float scale = 1 .0f;
       // 如果图片宽度大于控件宽度,但是图片高度小于控件 高度,我们要缩小图片
       if (imageWidth > width && imageHeight < height) {
         scale = width * 1 .0f / imageWidth;
       }
       // 如果图片宽度小于控件宽度,但是图片高度大于控件 高度,我们要缩小图片
       if (imageWidth < width && imageHeight > height) {
         scale = height * 1 .0f / imageHeight;
       }
       // 如果图片的宽度都 大于或小于控件宽度,我们则要对图片进行对应缩放,保证图片占满控件
       if ((imageWidth > width && imageHeight > height) || (imageWidth < width && imageHeight < height)) {
         scale = Math.min(width * 1 .0f / imageWidth, height * 1 .0f / imageHeight);
       }
       // 初始化对应的缩放值
       defaultScale = scale;
       doubleScale = defaultScale * 2 ;
       // 图片缩放后,将图片要移动到控件中心
       int dx = width / 2 - imageWidth / 2 ;
       int dy = height / 2 - imageHeight / 2 ;
       mScaleMatrix.postTranslate(dx, dy);
       mScaleMatrix.postScale(defaultScale, defaultScale, width / 2 , height / 2 );
       setImageMatrix(mScaleMatrix);
       isFirst = true ;
     }
   }
   @SuppressLint ( "ClickableViewAccessibility" )
   @Override
   public boolean onTouch(View v, MotionEvent event) {
     if (mGestureDetector.onTouchEvent(event)) { return true ; }
     float x = 0 ;
     float y = 0 ;
     int pointerCount = event.getPointerCount(); // 获取放在屏幕上的手指数量
     for ( int i = 0 ; i < pointerCount; i++) {
       x += event.getX(i);
       y += event.getY(i);
     }
     x /= pointerCount;
     y /= pointerCount;
     if (mLastPinterCount != pointerCount) {
       isCanDrag = false ;
       mLastX = x;
       mLastY = y;
 
     }
     mLastPinterCount = pointerCount;
     switch (event.getAction()) {
       case MotionEvent.ACTION_MOVE:
         float dx = x - mLastX;
         float dy = y - mLastY;
         isCanDrag = isMove(dx, dy);
         if (isCanDrag) {
           RectF rectf = getMatrixRectf();
           if ( null != getDrawable()) {
             isCheckLeft = isCheckTop = true ;
             if (rectf.width() < getWidth()) { // 如果图片宽度小于控件宽度(屏幕宽度)不允许横向移动
               dx = 0 ;
               isCheckLeft = false ;
             }
             if (rectf.height() < getHeight()) { // 如果图片高度小于控件高度(屏幕高度)不允许纵向移动
               dy = 0 ;
               isCheckTop = false ;
             }
             mScaleMatrix.postTranslate(dx, dy);
             checkTranslateWithBorder();
             setImageMatrix(mScaleMatrix);
           }
         }
         mLastX = x;
         mLastY = y;
         break ;
       case MotionEvent.ACTION_UP:
       case MotionEvent.ACTION_CANCEL:
         mLastPinterCount = 0 ;
         break ;
     }
     return true ;
   }
   /**
    * 移动图片时进行边界检查
    * @description:
    * @date 2016-1-8 下午4:02:24
    */
   private void checkTranslateWithBorder() {
     RectF rectf = getMatrixRectf();
     float delX = 0 ;
     float delY = 0 ;
     int width = getWidth();
     int height = getHeight();
     if (rectf.top > 0 && isCheckTop) {
       delY = -rectf.top;
     }
     if (rectf.bottom < height && isCheckTop) {
       delY = height - rectf.bottom;
     }
     if (rectf.left > 0 && isCheckLeft) {
       delX = -rectf.left;
     }
     if (rectf.right < width && isCheckLeft) {
       delX = width - rectf.right;
     }
     mScaleMatrix.postTranslate(delX, delY);
   }
   // 判断是否有移动
   private boolean isMove( float x, float y) {
     return Math.sqrt(x * x + y * y) > mTouchSlop;
   }
   /**
    * 获取图片的位置
    * @description:
    * @date 2016-1-8 上午9:02:10
    */
   private RectF getMatrixRectf() {
     Matrix matrix = mScaleMatrix;
     RectF recft = new RectF();
     if (getDrawable() != null ) {
       recft.set( 0 , 0 , getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
       matrix.mapRect(recft);
     }
     return recft;
   }
 
   // 获取当前图片的缩放值
   private float getScale() {
     float values[] = new float [ 9 ];
     mScaleMatrix.getValues(values);
     return values[Matrix.MSCALE_X];
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值