Android 基于手势进行图片缩放

1.触摸事件的处理

   当手指触摸屏幕时获取触摸点的个数,当触摸点只有一个时,当做平移操作处理,当触摸点为两个时则为放大缩小操作。平移操作记录下当前按下的点的坐标就行,如果是放大缩小操作,则计算出两点间的中点,后续放大和缩小以改点为中点进行.代码片段:

if(ev.getActionMasked()==MotionEvent.ACTION_DOWN||ev.getActionMasked()==MotionEvent.ACTION_POINTER_DOWN){
			if(!scroller.isFinished())
				scroller.abortAnimation();
			if(ev.getPointerCount()==1){
				downX=ev.getX();
				downY=ev.getY();
				isZooming=false;
			}else if(ev.getPointerCount()==2){
				preScale=scale;
				preTranslationX=translationX;//记录之前的x平移值
				preTranslationY=translationY;//记录前一次的y平移值
				touchDistance=(float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0));//计算两个触摸点之间的距离
				touchCenterX=(ev.getX(0) + ev.getX(1)) / 2.0f;//计算中点x 坐标
				touchCenterY=(ev.getY(0) + ev.getY(1)) / 2.0f;//计算y的中点坐标
				isZooming=true;
				isMoving=false;
			}
			
		}

2.平移后计算X和Y的偏移量计算


上图中缩放点为x,y对应代码中的touchCenterX和touchCenterY,x1和Y2对应之前的边界坐标(左边和上边,上图标的有问题)在程序中对应preTranslationX和,preTranslationY。x2和Y2为缩放后新的边界坐标(左边和上边)对应代码中的translationX和translationY。代码如下

	if(ev.getPointerCount()==2){
				//计算新的放大系数和移动的边界值
				scale = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)) / touchDistance *preScale;
				translationX = touchCenterX - (touchCenterX - preTranslationX) * (scale / preScale);
                translationY = touchCenterY - (touchCenterY - preTranslationY) * (scale / preScale);
                updateMinMax(scale);
                this.invalidate();
			}
3.每次放大缩小后边界值计算

  放大缩小后要重新计算最大最下边界值,用于在拖动图片时防止图片被拖出边界

private void updateMinMax(float scale) {
        int dw = (int) (getWidth()-scaleImgW)/2;
        int dh = (int) (getHeight()-scaleImgH)/2;
        if(scaleImgW*scale<getWidth()){
        	minX=maxX=-(int) (dw*scale-(int) (getWidth()-scaleImgW*scale)/2);
        }else{
        	if(scaleImgW<getWidth()){
        		maxX=-dw*scale;
        		minX=getWidth()-scaleImgW*scale+maxX;
        	}else{
        		maxX=0;
            	minX=getWidth()-scaleImgW*scale;
        	}
        }
        if(scaleImgH*scale<getHeight()){
        	minY=maxY=-(int) (dh*scale-(int) (getHeight()-scaleImgH*scale)/2);
        }else{
        	if(scaleImgH<getHeight()){
        		maxY=-dh*scale;
        		minY=getHeight()-scaleImgH*scale+maxY;
        	}else{
        		maxY=0;
            	minY=getHeight()-scaleImgH*scale;
        	}
        	
        }
        
    }
4.拖动过程中边界值得检查

private void checkMinMax(boolean zoom) {
        float moveToX = translationX;
        float moveToY = translationY;
        updateMinMax(scale);
        if (translationX < minX) {
            moveToX = minX;
        } else if (translationX > maxX) {
            moveToX = maxX;
        }
        if (translationY < minY) {
            moveToY = minY;
        } else if (translationY > maxY) {
            moveToY = maxY;
        }
        animateTo(scale, moveToX, moveToY);
    }

5.拖出边界后要进行还原

<span style="font-size:14px;">//放大缩小和平移动画
    private void animateTo(float newScale, float newTx, float newTy, int duration) {
        if (scale == newScale && translationX == newTx && translationY == newTy) {
            return;
        }
        animateToScale = newScale;
        animateToX = newTx;
        animateToY = newTy;
        animationStartTime = System.currentTimeMillis();
        imageMoveAnimation = new AnimatorSet();
        imageMoveAnimation.playTogether(ObjectAnimator.ofFloat(this, "animationValue", 0, 1));
        imageMoveAnimation.setInterpolator(interpolator);
        imageMoveAnimation.setDuration(duration);
        imageMoveAnimation.addListener(new AnimatorListenerAdapterProxy() {
            @Override
            public void onAnimationEnd(Animator animation) {
                imageMoveAnimation = null;
                ZoomImageView.this.invalidate();
            }
        });
        imageMoveAnimation.start();
    }</span>

6.重新进行绘制

<span style="font-size:14px;">//保存画布
		canvas.save();
		//先进行平移操作
		canvas.translate(translationX, translationY);
		//再进行缩放
		canvas.scale(scale,scale);
		//进行旋转
		canvas.rotate(rolateDegree, getWidth()/2, getHeight()/2);
		//根据图片的长和宽计算绘制区域
		float scaleX=(float)imgW/getWidth();
		float scaleY=(float)imgH/getHeight();
		float scale=scaleX>scaleY?scaleX:scaleY;
		scaleImgW=(int) (imgW/scale);
		scaleImgH=(int) (imgH/scale);
		imgDrawable.setBounds(caculateDrawRect(scaleImgW, scaleImgH));
		imgDrawable.draw(canvas);
		canvas.restore();</span>


效果图:



7.项目源码下载

http://download.csdn.net/detail/xiaibiancheng/9548435

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值