项目间隙研究了下PDF阅读器的代码,发现大部分源码都提供了翻页效果,而没有实现支持翻页的同时支持缩放的效果。下面给出实现的方案。有问题欢迎交流。
实现的整体思路是这样的。在一个相对布局中有两个自定义的view,一个用来翻页,一个用来缩放。初始化载入缩放的View,对这个View进行监听,这里坐了三种监听,翻页监听、缩放监听、点击监听。监听到翻页的时候,启用翻页View的回调,传给翻页View滑动开始的坐标值,然后交换View视图,即翻页View显示,缩放View隐藏。然后开始处理翻页的逻辑。翻页成功后置成初始化成功时的状态。下面贴一下核心代码。
翻页的自定义View用的开源的例子,主要原理就是贝塞尔曲线。这里就不再贴出来了。下面主要介绍下缩放的自定义View。
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
//判断手指的手势操作,这里为缩放模式
case MotionEvent.ACTION_POINTER_DOWN:
last.set(curr);
start.set(last);
mode = ZOOM;
isInClickArea = false;
break;
case MotionEvent.ACTION_DOWN:
//判断是否为缩放模式,如果saveScale比1大,就认为是缩放模式了。
if(saveScale - 1 > 0.001){
mode = ZOOM;
last.set(curr);
start.set(last);
}else{//拖拽模式
mode = DRAG;
int x = (int) event.getX();
//下面这段代码是用来处理点击事件的,onTouch事件会劫持onClick事件,所以这里如果down的坐标
//在屏幕的中间,这里定义的中间为屏幕三分之后的中间位置。返回false,自定义View就会响应onClick事件
if(x > (Config.SCREEN_WIDTH/3) && x < (Config.SCREEN_WIDTH*2/3)){
isInClickArea = true;
return false;
}
isInClickArea = false;
mode = DRAG;
downX = (int) event.getX();
downY = (int) event.getY();
mPagerListenr.pager(event);
startTime = System.nanoTime();
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM || saveScale - 1 > 0.001) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float fixTransX = getFixDragTrans(deltaX, viewWidth, origWidth * saveScale);
float fixTransY = getFixDragTrans(deltaY, viewHeight, origHeight * saveScale);
matrix.postTranslate(fixTransX, fixTransY);
fixTrans();
last.set(curr.x, curr.y);
}else if(mode == DRAG){
if(isInClickArea){
return false;
}
moveX = (int) event.getX();
moveY = (int) event.getY();
//回调函数
mPagerListenr.pagerNext(event);
}
break;
case MotionEvent.ACTION_UP:
firstMove = true;
if(mode == DRAG ){
if(isInClickArea){
return false;
}
mode = NONE;
//执行回调函数
return mPagerListenr.pagerNext(event);
}
mode = NONE;
reScale();
break;
case MotionEvent.ACTION_POINTER_UP:
firstMove = true;
if(mode == DRAG){
mode = NONE;
//执行回调函数
return mPagerListenr.pagerNext(event);
}
mode = NONE;
reScale();
break;
}
setImageMatrix(matrix);
invalidate();
return true;
}
});
setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mPagerListenr.onClick();
}
});
public interface PagerListener{
public void pager(MotionEvent event);
public boolean pagerNext(MotionEvent event);
public boolean onLongClick();
public void onClick();
}
private PagerListener mPagerListenr;
public void setOnPagerListener(PagerListener mPagerListenr){
this.mPagerListenr = mPagerListenr;
}
以上代码都是在自定义的View中,这个View继承自ImageView。
下面看下Activity的逻辑代码。
private void initPageImg(){
pageImg = (TouchImageView) findViewById(R.id.img_pageview);
pageImg.setImageBitmap(mCurPageBitmap);
pageImg.setMaxZoom(4f);
pageImg.setOnPagerListener(new PagerListener() {
@Override
public boolean onLongClick() {// ���ﴦ�?���¼�
// TODO Auto-generated method stub
//handleLongPressOnPageView();
return false;
}
@Override
public void pager(MotionEvent event) {
// TODO Auto-generated method stub
// if (event.getAction() == MotionEvent.ACTION_DOWN) {
mPager.abortAnimation();
mPager.calcCornerXY(event.getX(), event.getY());
// ��������滻bitmap
if (mPager.DragToRight()) {// ���һ�������ʾǰһҳ
if (pageNum == 0) {
return;
} else {
mCurPageBitmap = getBitmapByPageNo(pageNum);
mNextPageBitmap = mCurPageBitmap;
pageNum--;
mCurPageBitmap = getBitmapByPageNo(pageNum);
}
} else {// ���
大致就是这样子,需要源码的可以留下联系方式,有问题欢迎交流。