刚开始接触自定义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;
}
}