今回いわゆるページめくりのできるViewを作りたいと思いSurfaceViewを継承したものを作ってみました。
public class PageView extends SurfaceView implements OnTouchListener, Callback{
private int mWidth,mHeight;
private Bitmap prevImage; //左ページの画像
private Bitmap currImage; //現在表示中の画像
private Bitmap nextImage; //右ページの画像
private final Matrix matrix = new Matrix();
private Paint mPaint = new Paint();
private PageListener listener = null; //独自実装のリスナ
private int page = 0;
private int maxPage = 100;
public PageView(Context context) {
this(context, null);
}
public PageView(Context context, AttributeSet attrs){
super(context, attrs);
this.getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder){
this.setOnTouchListener(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){
mWidth = width;
mHeight = height;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
this.setOnTouchListener(null);
listener = null;
}
private PointF touchStartPoint = new PointF();
private PointF totalMove = new PointF();
private int touchMode = TOUCH_NONE;
private static final int TOUCH_NONE = 0;
private static final int TOUCH_FLICK = 1;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
//フリック操作開始
if(touchMode == TOUCH_NONE & event.getPointerCount() == 1){
touchStartPoint.x = event.getX();
touchMode = TOUCH_FLICK;
}
break;
case MotionEvent.ACTION_MOVE:
//フリック操作中
if(touchMode == TOUCH_FLICK){
if(event.getX() < touchStartPoint.x && page < maxPage){
turningPageRight(event.getX() - touchStartPoint.x);
}else if(event.getX() > touchStartPoint.x && page > 0){
turningPageLeft(event.getX() - touchStartPoint.x);
}
}
break;
case MotionEvent.ACTION_UP:
//フリック操作終了
if(touchMode == TOUCH_FLICK){
matrix.reset();
totalMove.x = event.getX() - touchStartPoint.x;
if(touchStartPoint.x - event.getX() > mWidth / 2 && page < maxPage){
//右向きにページめくり
listener.onTurnedRight();
toNext(prepareImage(listener.onChangedNext(page)));
//↑で次の右ページの画像を取得
}else if(event.getX() - touchStartPoint.x > mWidth / 2 && page > 0){
//左向きにページめくり
listener.onTurnedLeft();
toPrevious(prepareImage(listener.onChangedPrevious(page)));
//↑で次の左ページの画像を取得
}else{
this.doDraw();
}
touchMode = TOUCH_NONE;
}
break;
}
return true;
}
private void turningPageRight(float move){
matrix.reset();
matrix.postTranslate(move, 0.0f);
Matrix mat = new Matrix();
SurfaceHolder holder = getHolder();
Canvas canvas = holder.lockCanvas();
canvas.drawColor(0xff000000);
canvas.drawBitmap(currImage, matrix, mPaint);
mat.postTranslate(move + mWidth, 0.0f);
canvas.drawBitmap(nextImage, mat, mPaint);
holder.unlockCanvasAndPost(canvas);
}
private void turningPageLeft(float move){
matrix.reset();
matrix.postTranslate(move, 0.0f);
Matrix mat = new Matrix();
mat.postTranslate(move - mWidth, 0.0f);
SurfaceHolder holder = getHolder();
Canvas canvas = holder.lockCanvas();
canvas.drawColor(0xff000000);
canvas.drawBitmap(currImage, matrix, mPaint);
canvas.drawBitmap(prevImage, mat, mPaint);
holder.unlockCanvasAndPost(canvas);
}
protected void Draw(SurfaceHolder holder){
//TODO 描画処理
Canvas canvas = holder.lockCanvas();
canvas.drawColor(0xff000000);
canvas.drawBitmap(currImage, matrix, mPaint);
holder.unlockCanvasAndPost(canvas);
}
private Bitmap prepareImage(Bitmap res){
Bitmap result = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
float scaleX = (float) mWidth / res.getWidth();
float scaleY = (float) mHeight / res.getHeight();
Matrix m = new Matrix();
if(scaleX < scaleY){
m.preScale(scaleX, scaleX);
m.postTranslate(0, (mHeight - (res.getHeight() * scaleX) ) / 2);
}else if(scaleX > scaleY){
m.preScale(scaleY, scaleY);
m.postTranslate((mWidth - (res.getWidth() * scaleY) ) / 2, 0);
}else{
m.postScale(scaleX, scaleY);
}
Canvas canvas = new Canvas(result);
canvas.drawBitmap(res, m, new Paint());
return result;
}
public void toNext(Bitmap moreNext){
prevImage = currImage;
currImage = nextImage;
nextImage = moreNext;
page++;
this.doDraw();
}
public void toPrevious(Bitmap morePrev){
nextImage = currImage;
currImage = prevImage;
prevImage = morePrev;
page--;
this.doDraw();
}
public void setListener(PageListener lis){
if(lis != null){
listener = lis;
}
}
public void doDraw(){
Draw(getHolder());
}
}
動きがカクカクした感じになってしまいました。
そこで滑らかにページめくりをする方法をお教え願いたいです。
(画面の端までページが移動するような感じ)
どうかよろしくお願いします。