自定义View之图片放大、缩小、移动

本文探讨如何创建一个自定义View,用于展示图片并支持放大、缩小和移动功能。通过重写onTouch()和onDraw()方法,根据触摸手势识别单指移动和双指缩放操作。最大放大倍数为4倍,最小缩小至图片宽度或高度小于等于View的尺寸。源码可供下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚开始接触自定义View的时候觉得用自定义View特别麻烦,现在感觉很有趣,根本停不下来。

本文介绍一个可以用于图片查看的自定义View,可以放大、缩小、移动查看图片。跟我前文的一篇博客《关于android照片瀑布流的思考》一起组成一个照片查看器。

说一下思路直接上代码。主要是重写View的onTouch()方法和onDraw()方法。

1、在onTouch()方法中捕获触摸的手势及动作,做出相应的操作。

如,手的按下、抬起;操作手指是一个还是两个。

本View的功能主要是实现放大、缩小、移动查看图片,所以主要是要记录手指移动的距离。一个手指就说明是要移动图片,主要记录手指移动的距离;两个手指就说明是要放大、缩小图片,则主要记录两指间的距离,以确定是放大还是缩小,以及伸缩倍数;本例最大放大四倍;最小缩小到宽或高小于等于View的宽或高。


	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getActionMasked()) {
		case MotionEvent.ACTION_POINTER_DOWN:
			//when two fingers down,record the distance between the two fingers
			if (event.getPointerCount() == 2) {
				lastFingersDistance = getDistanceBetweenFingers(event);
			}

			break;
		case MotionEvent.ACTION_MOVE:
			if (event.getPointerCount() == 1) {
				float moveX = event.getX();
				float moveY = event.getY();
				if (lastMoveX == -1 && lastMoveY == -1) {
					lastMoveX = moveX;
					lastMoveY = moveY;
				}
				movedDisX = moveX - lastMoveX;
				movedDisY = moveY - lastMoveY;
				currentState = STATE_MOVE;
				
				invalidate();
				lastMoveX=moveX;
				lastMoveY=moveY;
			} else if (event.getPointerCount() == 2) {
				double moveDis=getDistanceBetweenFingers(event);
				if(moveDis>lastFingersDistance){
					currentState=STATE_ZOOM_OUT;
				}else if(moveDis<lastFingersDistance){
					currentState=STATE_ZOOM_IN;
				}
				
				float zoomRatio=(float)(moveDis/lastFingersDistance);
				if((currentState==STATE_ZOOM_OUT && mRatio<MAX_ZOOM_OUT_MUL*minRatio) || 
						(currentState==STATE_ZOOM_IN && mRatio>minRatio)){					
					mRatio=mRatio*zoomRatio;	
					if(mRatio>MAX_ZOOM_OUT_MUL*minRatio)
						mRatio=MAX_ZOOM_OUT_MUL*minRatio;
					if(mRatio<minRatio)
						mRatio=minRatio;
					
					invalidate();
				lastFingersDistance=moveDis;
				}				
			}
			break;
		case MotionEvent.ACTION_POINTER_UP:
			if(event.getPointerCount() == 2){
				lastMoveX=-1;
				lastMoveY=-1;
			}
			break;
		case MotionEvent.ACTION_UP:
			lastMoveX=-1;
			lastMoveY=-1;
			break;
		}

		return true;
	}

event.getActionMasked()表示多点触控监测点;在1.6~2.1中并没有event.getActionMasked(),从源码中我们可以看到该方法就是对event.getAction()& MotionEvent.ACTION_MASK的封装。所以最好event.getActionMasked()替换为event.getAction()& MotionEvent.ACTION_MASK就个实现多版本的兼容。

event.getPointerCount()方法可以获取按下手指的个数。


2、在OnDraw中绘制图片

我们知道,View是在OnDraw()中绘制界面的,此处不多做说明。主要是根据不同状态绘制不同界面。

@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		switch (currentState) {
		case STATE_INIT:
			initBitmap(canvas);
			break;
		case STATE_MOVE:
			move(canvas);
			break;
		case STATE_ZOOM_OUT:
		case STATE_ZOOM_IN:
			zoom(canvas);
			break;
		default:
			canvas.drawBitmap(mBitmap, matrix, null);
			break;
		}

	}


下载源码





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值