Android实现翻页功能原理

来源:互联网 发布:iphone赚钱软件排行 编辑:程序博客网 时间:2024/05/22 18:55

第一种翻页效果如下:

 

实现原理:

当前手指触摸点为a,则 a点坐标为(ax,ay), 由三角形acb与三角形cmb为对称三角形并且直线cp为am垂直平分线,则 B点坐标为(ax/2,ay/2)。

作gf垂直于om且cb垂直于am, 三角形cfg与gfm相似,则 cf:gf = gf:mf      cf=(gf * gf) / mf     gf长度为g点纵坐标     mf长度为g点横坐标   

cf长度可求    c点坐标可求 由c点、g点可确定过两点间的直线, 当该直线中x=0时求出与y足交点。

 

第二种翻页效果

实现原理:

使用贝赛尔曲线。曲线有四个点:起始点、终止点(也称锚点)以及两个相互分离的中间点。滑动两个中间点,贝塞尔曲线的形状会发生变化。

根据第一种翻页效果原理可以确定a、e、h、f、g ,由eh平行于cj且af垂直于eh,则 af垂直于cj则三角形egf相似于三角形cnf 则有ef:cf = gf:nf 。

设n为ag中点 则有cf=(3/2)*ef ,则c点坐标可求 由c点、k点坐标已知可知过两点间的直线

由该直线可计算与y轴相交点j 由a、e、c、j可计算两条直线的相交点b 同理可求点k。

 

在Android中的具体实现步骤:

起始页展示

1.创建屏幕尺寸的bmp 2.将图片转化为canvas 3.获取起始页面数据 3.在canvas中绘制起始页数据 4.在当前视图中复写onDraw进行重绘出bmp对象

翻页处理

1.初始化时创建两个bmp(bmp1、bmp2)并将其转换为canvas(canvas1、canvas2)

2.获取手势首次触摸的区域 (例:当首次点击屏幕的位置x<50&&y<50则为左上角)

3.根据首次点击区域判断需要展示的数据(例:首次点击处于左侧区域【左上、左下】的则判断操作为下一页操作)

4.获取下一页中数据并绘制出来在canvas2中

5.根据1中获取的区域位置调用起始动画使视图移动到手势首次点击位置

6.获取手势每次移动的坐标并根据移动坐标计算绘制的各个点的坐标

7.每次移动刷新视图

源码示例下载1

源码示例下载2

源码实例1:

项目结构:

PageWidget:

复制代码
package sf.hmg.turntest; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.Region; import android.graphics.drawable.GradientDrawable; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class PageWidget extends View { private static final String TAG = "hmg"; private int mWidth = 480; private int mHeight = 800; private int mCornerX = 0; // 拖拽点对应的页脚  private int mCornerY = 0; private Path mPath0; private Path mPath1;        Bitmap mCurPageBitmap = null; //当前页  Bitmap mCurPageBackBitmap = null;     Bitmap mNextPageBitmap = null;      PointF mTouch = new PointF(); // 拖拽点  PointF mBezierStart1 = new PointF(); // 贝塞尔曲线起始点  PointF mBezierControl1 = new PointF(); // 贝塞尔曲线控制点  PointF mBeziervertex1 = new PointF(); // 贝塞尔曲线顶点  PointF mBezierEnd1 = new PointF(); // 贝塞尔曲线结束点  PointF mBezierStart2 = new PointF(); // 另一条贝塞尔曲线  PointF mBezierControl2 = new PointF();    PointF mBeziervertex2 = new PointF();    PointF mBezierEnd2 = new PointF(); float mMiddleX; float mMiddleY; float mDegrees; float mTouchToCornerDis; boolean mIsRTandLB; // 是否属于右上左下 // for test  float mMaxLength = (float) Math.hypot(480, 800); int[] mBackShadowColors; int[] mFrontShadowColors;    GradientDrawable mBackShadowDrawableLR;    GradientDrawable mBackShadowDrawableRL;    GradientDrawable mFolderShadowDrawableLR;    GradientDrawable mFolderShadowDrawableRL;       GradientDrawable mFrontShadowDrawableHBT;    GradientDrawable mFrontShadowDrawableHTB;    GradientDrawable mFrontShadowDrawableVLR;    GradientDrawable mFrontShadowDrawableVRL; private Bitmap mBitmap; private Canvas mCanvas; private Paint mBitmapPaint;    Paint paint; public PageWidget(Context context) { super(context); // TODO Auto-generated constructor stub  mPath0 = new Path();    mPath1 = new Path();    createDrawable(); // ---------------------------------------  mBitmap = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);    mCanvas = new Canvas(mBitmap);    mBitmapPaint = new Paint(Paint.DITHER_FLAG);        mCurPageBitmap = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);    Canvas canvas = new Canvas(mCurPageBitmap);    paint = new Paint();    canvas.drawColor(Color.YELLOW);    canvas.drawBitmap(mCurPageBitmap, 0, 0, paint);    mNextPageBitmap = Bitmap        .createBitmap(480, 800, Bitmap.Config.ARGB_8888);    canvas = new Canvas(mNextPageBitmap);    canvas.drawColor(Color.GREEN);    canvas.drawBitmap(mNextPageBitmap, 0, 0, paint);    } /** *  Author :  hmg25     *  Version:  1.0      *  Description : 计算拖拽点对应的拖拽脚 */ private void calcCornerXY(float x, float y) { if (x <= mWidth / 2)        mCornerX = 0; else mCornerX = mWidth; if (y <= mHeight / 2)        mCornerY = 0; else mCornerY = mHeight; if ((mCornerX == 0 && mCornerY == mHeight)        || (mCornerX == mWidth && mCornerY == 0))        mIsRTandLB = true; else mIsRTandLB = false;    }    @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub  if (event.getAction() == MotionEvent.ACTION_MOVE) {       mCanvas.drawColor(0xFFAAAAAA);        mTouch.x = event.getX();        mTouch.y = event.getY(); this.postInvalidate();    } if (event.getAction() == MotionEvent.ACTION_DOWN) {        mCanvas.drawColor(0xFFAAAAAA);        mTouch.x = event.getX();        mTouch.y = event.getY();        calcCornerXY(mTouch.x, mTouch.y); this.postInvalidate();    } if (event.getAction() == MotionEvent.ACTION_UP) {       mCanvas.drawColor(0xFFAAAAAA);        mTouch.x = mCornerX;        mTouch.y = mCornerY; this.postInvalidate();    } // return super.onTouchEvent(event);  return true;    } /** *  Author :  Administrator     *  Version:  1.0      *  Description : 求解直线P1P2和直线P3P4的交点坐标 */ public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {    PointF CrossP = new PointF(); // 二元函数通式: y=ax+b  float a1 = (P2.y - P1.y) / (P2.x - P1.x); float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x); float a2 = (P4.y - P3.y) / (P4.x - P3.x); float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);    CrossP.x = (b2 - b1) / (a1 - a2);    CrossP.y = a1 * CrossP.x + b1; return CrossP;    } private void calcPoints() {    mMiddleX = (mTouch.x + mCornerX) / 2;    mMiddleY = (mTouch.y + mCornerY) / 2;    mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)        * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);    mBezierControl1.y = mCornerY;    mBezierControl2.x = mCornerX;    mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)        * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);    Log.i("hmg", "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);    Log.i("hmg", "mBezierControl1.x  " + mBezierControl1.x        + "  mBezierControl1.y  " + mBezierControl1.y);    Log.i("hmg", "mBezierControl2.x  " + mBezierControl2.x        + "  mBezierControl2.y  " + mBezierControl2.y);    mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)        / 2;    mBezierStart1.y = mCornerY;    mBezierStart2.x = mCornerX;    mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)        / 2;    Log.i("hmg", "mBezierStart1.x  " + mBezierStart1.x        + "  mBezierStart1.y  " + mBezierStart1.y);    Log.i("hmg", "mBezierStart2.x  " + mBezierStart2.x        + "  mBezierStart2.y  " + mBezierStart2.y);    mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),        (mTouch.y - mCornerY));    mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,        mBezierStart2);    mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,        mBezierStart2);    Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "        + mBezierEnd1.y);    Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "        + mBezierEnd2.y); /* * mBeziervertex1.x 推导     * ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于     * (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4 */ mBeziervertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;    mBeziervertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;    mBeziervertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;    mBeziervertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;    Log.i("hmg", "mBeziervertex1.x  " + mBeziervertex1.x        + "  mBeziervertex1.y  " + mBeziervertex1.y);    Log.i("hmg", "mBeziervertex2.x  " + mBeziervertex2.x        + "  mBeziervertex2.y  " + mBeziervertex2.y);    } private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {    mPath0.reset();    mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);    mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,        mBezierEnd1.y);    mPath0.lineTo(mTouch.x, mTouch.y);    mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);    mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,        mBezierStart2.y);    mPath0.lineTo(mCornerX, mCornerY);    mPath0.close();    canvas.save();    canvas.clipPath(path, Region.Op.XOR);    canvas.drawBitmap(bitmap, 0, 0, null);    canvas.restore();    } private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {    mPath1.reset();    mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);    mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);    mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);    mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);    mPath1.lineTo(mCornerX, mCornerY);    mPath1.close();    mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x        - mCornerX, mBezierControl2.y - mCornerY)); float f5 = mTouchToCornerDis /4; int leftx; int rightx;    GradientDrawable  mBackShadowDrawable; if(mIsRTandLB)    {               leftx=(int)(mBezierStart1.x - 1);        rightx= (int)(mBezierStart1.x +mTouchToCornerDis /4+ 1);        mBackShadowDrawable=mBackShadowDrawableLR;    }else {                leftx=(int)(mBezierStart1.x - mTouchToCornerDis/4 - 1);            rightx= (int) mBezierStart1.x + 1;        mBackShadowDrawable=mBackShadowDrawableRL;    }    Log.i("hmg", "leftx  " + leftx        + "   rightx  " +  rightx);    canvas.save();    canvas.clipPath(mPath0);    canvas.clipPath(mPath1, Region.Op.INTERSECT);    canvas.drawBitmap(bitmap, 0, 0, null);    canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);    mBackShadowDrawable.setBounds(leftx,        (int)mBezierStart1.y, rightx,        (int) (mMaxLength + mBezierStart1.y));    mBackShadowDrawable.draw(canvas);        canvas.restore();    } public void setBitmaps(Bitmap bm1, Bitmap bm2, Bitmap bm3) {    mCurPageBitmap = bm1;    mCurPageBackBitmap = bm2;    mNextPageBitmap = bm3;    }    @Override protected void onDraw(Canvas canvas) {    canvas.drawColor(0xFFAAAAAA);    calcPoints();    drawCurrentPageArea(mCanvas, mCurPageBitmap, mPath0);    drawNextPageAreaAndShadow(mCanvas, mNextPageBitmap);        drawCurrentPageShadow(mCanvas);    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);    } /** *  Author :  hmg25     *  Version:  1.0      *  Description : 创建阴影的GradientDrawable */ private void createDrawable() { int[] color = { 0x333333, 0xB0333333 };    mFolderShadowDrawableRL = new GradientDrawable(        GradientDrawable.Orientation.RIGHT_LEFT, color);    mFolderShadowDrawableRL        .setGradientType(GradientDrawable.LINEAR_GRADIENT);    mFolderShadowDrawableLR = new GradientDrawable(        GradientDrawable.Orientation.LEFT_RIGHT, color);    mFolderShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mBackShadowColors = new int[] { 0xFF111111, 0x111111 };    mBackShadowDrawableRL = new GradientDrawable(        GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);    mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mBackShadowDrawableLR = new GradientDrawable(        GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);    mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mFrontShadowColors = new int[] { 0x80888888, 0x888888 };    mFrontShadowDrawableVLR = new GradientDrawable(        GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);    mFrontShadowDrawableVLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mFrontShadowDrawableVRL = new GradientDrawable(        GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);    mFrontShadowDrawableVRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mFrontShadowDrawableHTB = new GradientDrawable(        GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);    mFrontShadowDrawableHTB.setGradientType(GradientDrawable.LINEAR_GRADIENT);    mFrontShadowDrawableHBT = new GradientDrawable(        GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);    mFrontShadowDrawableHBT.setGradientType(GradientDrawable.LINEAR_GRADIENT);    } public void drawCurrentPageShadow(Canvas canvas)    { //注:拖拽顶点的阴影,定位有问题,待修改~~  double d1 = Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x-mBezierControl1.x); // double d3 =(float)Math.cos(d1) *  25*1.414f;  double d3 =(float) 25/Math.cos(d1) ; // float x = (float)(mTouch.x-d3); // float y = mTouch.y -(float)Math.sin(d1) * 25*1.414f;  float x = (float)(mTouch.x-d3); float y =(float)( mTouch.y -d3);          mPath1.reset();          mPath1.moveTo(x, y);          mPath1.lineTo(mTouch.x, mTouch.y);          mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);          mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);          mPath1.close(); float rotateDegrees;           canvas.save();                   canvas.clipPath(mPath0, Region.Op.XOR);         canvas.clipPath(mPath1,Region.Op.INTERSECT); int leftx; int rightx;            GradientDrawable  mCurrentPageShadow; if(mIsRTandLB)        {                   leftx=(int)(mBezierControl1.x);            rightx= (int)mBezierControl1.x+25;            mCurrentPageShadow=mFrontShadowDrawableVLR;        }else {                    leftx=(int)(mBezierControl1.x-25);                rightx= (int) mBezierControl1.x;            mCurrentPageShadow=mFrontShadowDrawableVRL;        }          rotateDegrees= (float)Math.toDegrees(Math.atan2(mTouch.x-mBezierControl1.x,mBezierControl1.y-mTouch.y));           canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);                            mCurrentPageShadow.setBounds(leftx, (int)(mBezierControl1.y-500), rightx, (int)(mBezierControl1.y));                   mCurrentPageShadow.draw(canvas);          canvas.restore();                    mPath1.reset();          mPath1.moveTo(x, y);          mPath1.lineTo(mTouch.x, mTouch.y);          mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);          mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);          mPath1.close();          canvas.save();          canvas.clipPath(mPath0, Region.Op.XOR);          canvas.clipPath(mPath1,Region.Op.INTERSECT); if(mIsRTandLB)        {                 leftx=(int)(mBezierControl2.y);                rightx=(int)(mBezierControl2.y+25);            mCurrentPageShadow=mFrontShadowDrawableHTB;        }else {                    leftx=(int)(mBezierControl2.y-25);                rightx=(int)(mBezierControl2.y);            mCurrentPageShadow=mFrontShadowDrawableHBT;        }          rotateDegrees= (float)Math.toDegrees(Math.atan2(mBezierControl2.y-mTouch.y,mBezierControl2.x-mTouch.x));           canvas.rotate( rotateDegrees, mBezierControl2.x, mBezierControl2.y);          mCurrentPageShadow.setBounds((int)(mBezierControl2.x-500),leftx , (int)(mBezierControl2.x), rightx );                   mCurrentPageShadow.draw(canvas);          canvas.restore();    }   }
复制代码

turntest:

复制代码
package sf.hmg.turntest; import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class turntest extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);    getWindow().setFlags(        WindowManager.LayoutParams.FLAG_FULLSCREEN,        WindowManager.LayoutParams.FLAG_FULLSCREEN);         setContentView(new PageWidget(this));             }      }
复制代码

实例1效果图:

------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------------------------------------------------------

实例2代码:

工程结构图:

MainActivity:

复制代码
package com.xin.book; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import com.xin.book.view.BookAdapter; import com.xin.book.view.BookLayout; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);         BookLayout bk = new BookLayout(this);         List<String> str = new ArrayList<String>();         str.add("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");         str.add("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");         str.add("ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc");         str.add("ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd");         str.add("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");         str.add("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");         BookAdapter ba = new BookAdapter(this);         ba.addItem(str);         bk.setPageAdapter(ba);         setContentView(bk);    }}
复制代码

BookAdapter:

复制代码
package com.xin.book.view; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Color; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; import android.widget.TextView; import com.xin.book.R; public class BookAdapter implements IAdapter{ private List<String> strList = new ArrayList<String>(); private Context mContext; public BookAdapter(Context context) { super(); this.mContext = context;    } public void addItem(List<String> list){        strList.addAll(list);    } public int getCount() { return strList.size();    } public String getItem(int position) { return strList.get(position);    } public long getItemId(int position) { return position;    } public View getView(int position) {        TextView textView = new TextView(mContext);        textView.setText(strList.get(position));        textView.setTextColor(Color.BLACK);        textView.setTextSize(32);        textView.setBackgroundColor(Color.WHITE);        textView.setBackgroundResource(R.drawable.ly);        textView.setPadding(10, 10, 10, 10);        textView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); return textView;    }}
复制代码

BookLayout:

复制代码
package com.xin.book.view; import java.util.Date; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.PorterDuffXfermode; import android.graphics.Shader; import android.graphics.PorterDuff.Mode; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.GestureDetector.OnGestureListener; import android.widget.FrameLayout; import android.widget.LinearLayout; public class BookLayout extends FrameLayout { public static final String LOG_TAG = "HarHar"; private int totalPageNum; private Context mContext; private boolean hasInit = false; private final int defaultWidth = 600, defaultHeight = 400; private int contentWidth = 0; private int contentHeight = 0; private View currentPage,middlePage,nextPage,prevPage; private LinearLayout invisibleLayout; private LinearLayout mainLayout; private BookView mBookView; private Handler aniEndHandle; private static boolean closeBook = false; private Corner mSelectCorner; private final int clickCornerLen = 250 * 250; // 50dip  private float scrollX = 0, scrollY = 0; private int indexPage = 0; private BookState mState; private Point aniStartPos; private Point aniStopPos; private Date aniStartTime; private long aniTime = 800; private long timeOffset = 10; // private Listener mListener;  private BookAdapter mPageAdapter; private GestureDetector mGestureDetector; private BookOnGestureListener mGestureListener; public BookLayout(Context context) { super(context);        Init(context);    } public BookLayout(Context context, AttributeSet attrs) { super(context, attrs);        Init(context);    } public BookLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle);        Init(context);    } public void setPageAdapter(BookAdapter pa) {        Log.d(LOG_TAG, "setPageAdapter");        mPageAdapter = pa;    } public void Init(Context context) {        Log.d(LOG_TAG, "Init");        totalPageNum = 0;        mContext = context;        mSelectCorner = Corner.None;        mGestureListener = new BookOnGestureListener();        mGestureDetector = new GestureDetector(mGestureListener);        mGestureDetector.setIsLongpressEnabled(false);        aniEndHandle = new Handler(); this.setOnTouchListener(touchListener); this.setLongClickable(true);    } protected void dispatchDraw(Canvas canvas) {        Log.d(LOG_TAG, "dispatchDraw"); super.dispatchDraw(canvas); if (!hasInit) {            hasInit = true;            indexPage = 0; if (mPageAdapter == null) { throw new RuntimeException("please set the PageAdapter on init");            }            totalPageNum = mPageAdapter.getCount();            mainLayout = new LinearLayout(mContext);            mainLayout.setLayoutParams(new LayoutParams(contentWidth, contentHeight));            mainLayout.setBackgroundColor(0xffffffff);            mState = BookState.READY;            invisibleLayout = new LinearLayout(mContext);            invisibleLayout.setLayoutParams(new LayoutParams(contentWidth, contentHeight)); this.addView(invisibleLayout); this.addView(mainLayout);            mBookView = new BookView(mContext);            mBookView.setLayoutParams(new LayoutParams(contentWidth, contentHeight)); this.addView(mBookView);            updatePageView();            invalidate();        } else if (mState == BookState.READY) {            mBookView.update();        }    } /** * 此方法做过修改,改成一页显示 */ public void updatePageView() {        Log.d(LOG_TAG, "updatePageView"); if (indexPage < 0 || indexPage > totalPageNum - 1) { return;        }        invisibleLayout.removeAllViews();        mainLayout.removeAllViews(); /*当前页*/ currentPage = mPageAdapter.getView(indexPage); if(currentPage == null){            currentPage = new WhiteView(mContext);        }        currentPage.setLayoutParams(new LayoutParams(contentWidth,contentHeight));        mainLayout.addView(currentPage); /*背景页*/ middlePage = new WhiteView(mContext);        middlePage.setLayoutParams(new LayoutParams(contentWidth,contentHeight));        invisibleLayout.addView(middlePage); /*前一页*/ prevPage = null; if(indexPage>0){            prevPage = mPageAdapter.getView(indexPage-1);        } if(prevPage==null){            prevPage = new WhiteView(mContext);        }        prevPage.setLayoutParams(new LayoutParams(contentWidth,contentHeight));        invisibleLayout.addView(prevPage); /*后一页*/ nextPage = null; if(indexPage<totalPageNum-1){            nextPage = mPageAdapter.getView(indexPage + 1);        } if(nextPage==null){            nextPage = new WhiteView(mContext);        }        nextPage.setLayoutParams(new LayoutParams(contentWidth,contentHeight));        invisibleLayout.addView(nextPage);                Log.d(LOG_TAG, "updatePageView finish");    }    OnTouchListener touchListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) {            Log.d(LOG_TAG, "onTouch " + " x: " + event.getX() + " y: " + event.getY() + " mState:" + mState);            mGestureDetector.onTouchEvent(event); int action = event.getAction(); if (action == MotionEvent.ACTION_UP && mSelectCorner != Corner.None && mState == BookState.TRACKING) { if (mState == BookState.ANIMATING) return false; if(mSelectCorner == Corner.LeftTop){ if(scrollX<contentWidth/2){                        aniStopPos = new Point(0,0);                    }else{                        aniStopPos = new Point(2*contentWidth,0);                    }                }else if(mSelectCorner == Corner.RightTop){ if(scrollX<contentWidth/2){                        aniStopPos = new Point(-contentWidth,0);                    }else{                        aniStopPos = new Point(contentWidth,0);                    }                }else if(mSelectCorner == Corner.LeftBottom){ if(scrollX<contentWidth/2){                        aniStopPos = new Point(0,contentHeight);                    }else{                        aniStopPos = new Point(2*contentWidth,contentHeight);                    }                }else if(mSelectCorner == Corner.RightBottom){ if(scrollX<contentWidth/2){                        aniStopPos = new Point(-contentWidth,contentHeight);                    }else{                        aniStopPos = new Point(contentWidth,contentHeight);                    }                }                aniStartPos = new Point((int) scrollX, (int) scrollY);                aniTime = 800;                mState = BookState.ABOUT_TO_ANIMATE;                closeBook = true;                aniStartTime = new Date();                mBookView.startAnimation();            } return false;        }    }; class BookOnGestureListener implements OnGestureListener { public boolean onDown(MotionEvent event) {            Log.d(LOG_TAG, "onDown"); if (mState == BookState.ANIMATING) return false; float x = event.getX(), y = event.getY(); int w = contentWidth, h = contentHeight; if (x * x + y * y < clickCornerLen) { if (indexPage > 0) {                    mSelectCorner = Corner.LeftTop;                    aniStartPos = new Point(0, 0);                }            } else if ((x - w) * (x - w) + y * y < clickCornerLen) { if (indexPage < totalPageNum - 1) {                    mSelectCorner = Corner.RightTop;                    aniStartPos = new Point(contentWidth, 0);                }            } else if (x * x + (y - h) * (y - h) < clickCornerLen) { if (indexPage > 0) {                    mSelectCorner = Corner.LeftBottom;                    aniStartPos = new Point(0, contentHeight);                }            } else if ((x - w) * (x - w) + (y - h) * (y - h) < clickCornerLen) { if (indexPage < totalPageNum - 1) {                    mSelectCorner = Corner.RightBottom;                    aniStartPos = new Point(contentWidth, contentHeight);                }            } if (mSelectCorner != Corner.None) {                aniStopPos = new Point((int) x, (int) y);                aniTime = 800;                mState = BookState.ABOUT_TO_ANIMATE;                closeBook = false;                aniStartTime = new Date();                mBookView.startAnimation();            } return false;        } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {            Log.d(LOG_TAG, "onFling velocityX:" + velocityX + " velocityY:" + velocityY); if (mSelectCorner != Corner.None) { if (mSelectCorner == Corner.LeftTop) { if (velocityX < 0) {                        aniStopPos = new Point(0, 0);                    } else {                        aniStopPos = new Point(2*contentWidth, 0);                    }                }else if( mSelectCorner == Corner.RightTop){ if (velocityX < 0) {                        aniStopPos = new Point(-contentWidth, 0);                    } else {                        aniStopPos = new Point(contentWidth, 0);                    }                }else if (mSelectCorner == Corner.LeftBottom ) { if (velocityX < 0) {                        aniStopPos = new Point(0, contentHeight);                    } else {                        aniStopPos = new Point(2*contentWidth, contentHeight);                    }                }else if( mSelectCorner == Corner.RightBottom){ if (velocityX < 0) {                        aniStopPos = new Point(-contentWidth, contentHeight);                    } else {                        aniStopPos = new Point(contentWidth, contentHeight);                    }                }                Log.d(LOG_TAG, "onFling animate");                aniStartPos = new Point((int) scrollX, (int) scrollY);                aniTime = 1000;                mState = BookState.ABOUT_TO_ANIMATE;                closeBook = true;                aniStartTime = new Date();                mBookView.startAnimation();            } return false;        } public void onLongPress(MotionEvent e) {            Log.d(LOG_TAG, "onLongPress");        } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            mState = BookState.TRACKING; if (mSelectCorner != Corner.None) {                scrollX = e2.getX();                scrollY = e2.getY();                mBookView.startAnimation();            } return false;        } public void onShowPress(MotionEvent e) {            Log.d(LOG_TAG, "onShowPress");        } public boolean onSingleTapUp(MotionEvent e) {            Log.d(LOG_TAG, "onSingleTapUp"); if (mSelectCorner != Corner.None) { if (mSelectCorner == Corner.LeftTop) { if (scrollX < contentWidth / 2) {                        aniStopPos = new Point(0, 0);                    } else {                        aniStopPos = new Point(2*contentWidth, 0);                    }                } else if(mSelectCorner == Corner.RightTop){ if (scrollX < contentWidth / 2) {                        aniStopPos = new Point(-contentWidth, 0);                    } else {                        aniStopPos = new Point(contentWidth, 0);                    }                }else if (mSelectCorner == Corner.LeftBottom) { if (scrollX < contentWidth / 2) {                        aniStopPos = new Point(0, contentHeight);                    } else {                        aniStopPos = new Point(2*contentWidth, contentHeight);                    }                }else if(mSelectCorner == Corner.RightBottom){ if (scrollX < contentWidth / 2) {                        aniStopPos = new Point(-contentWidth, contentHeight);                    } else {                        aniStopPos = new Point(contentWidth, contentHeight);                    }                }                aniStartPos = new Point((int) scrollX, (int) scrollY);                aniTime = 800;                mState = BookState.ABOUT_TO_ANIMATE;                closeBook = true;                aniStartTime = new Date();                mBookView.startAnimation();            } return false;        }    } protected void onFinishInflate() {        Log.d(LOG_TAG, "onFinishInflate"); super.onFinishInflate();    } protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b);        contentWidth = this.getWidth();        contentHeight = this.getHeight(); if (contentWidth == 0)            contentWidth = defaultWidth; if (contentHeight == 0)            contentHeight = defaultHeight;        Log.d(LOG_TAG, "onLayout, width:" + contentWidth + " height:" + contentHeight);    } class BookView extends SurfaceView implements SurfaceHolder.Callback {        DrawThread dt;        SurfaceHolder surfaceHolder;        Paint mDarkPaint = new Paint();        Paint mPaint = new Paint();        Bitmap tmpBmp = Bitmap.createBitmap(contentWidth, contentHeight, Bitmap.Config.ARGB_8888);        Canvas mCanvas = new Canvas(tmpBmp);        Paint bmpPaint = new Paint();        Paint ivisiblePaint = new Paint(); public BookView(Context context) { super(context);            surfaceHolder = getHolder();            surfaceHolder.addCallback(this);            mDarkPaint.setColor(0x88000000);            Shader mLinearGradient = new LinearGradient(0, 0, contentWidth, 0, new int[] { 0x00000000, 0x33000000,                    0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.MIRROR);            mPaint.setAntiAlias(true);            mPaint.setShader(mLinearGradient);            bmpPaint.setFilterBitmap(true);            bmpPaint.setAntiAlias(true);            ivisiblePaint.setAlpha(0);            ivisiblePaint.setFilterBitmap(true);            ivisiblePaint.setAntiAlias(true);            ivisiblePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));        } public void startAnimation() { if (dt == null) {                Log.d(LOG_TAG, "startAnimation");                dt = new DrawThread(this, getHolder());                dt.start();            }        } public void stopAnimation() {            Log.d(LOG_TAG, "stopAnimation"); if (dt != null) {                dt.flag = false;                Thread t = dt;                dt = null;                t.interrupt();            }        } public void drawLT(Canvas canvas) { double dx = contentWidth - scrollX, dy = scrollY; double len = Math.sqrt(dx * dx + dy * dy); if (len > contentWidth) {                scrollX = (float)(contentWidth - contentWidth*dx/len);                scrollY = (float)(contentWidth*dy/len);            } double px = scrollX; double py = scrollY; double arc = 2 * Math.atan(py / px) * 180 / Math.PI;            Matrix m = new Matrix();            m.postTranslate(scrollX - contentWidth, scrollY);            m.postRotate((float) (arc), scrollX, scrollY);            middlePage.draw(mCanvas);            Paint ps = new Paint();            Shader lg1 = new LinearGradient(contentWidth , 0, contentWidth - (float) px, (float) py, new int[] {                    0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg1);            mCanvas.drawRect(0, 0, contentWidth , contentHeight, ps);            canvas.drawBitmap(tmpBmp, m, bmpPaint);            prevPage.draw(mCanvas);            Shader lg2 = new LinearGradient(scrollX, scrollY, 0, 0, new int[] { 0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg2);            mCanvas.drawRect(0, 0, contentWidth , contentHeight, ps);            arc = arc * Math.PI / 360;            Path path = new Path(); double r = Math.sqrt(px * px + py * py); double p1 = r / (2 * Math.cos(arc)); double p2 = r / (2 * Math.sin(arc));            Log.d(LOG_TAG, "p1: " + p1 + " p2:" + p2); if (arc == 0) {                path.moveTo((float) p1, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo((float) p1, contentHeight);                path.close();            } else if (p2 > contentHeight || p2 < 0) { double p3 = (p2 - contentHeight) * Math.tan(arc);                path.moveTo((float) p1, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo((float) p3, contentHeight);                path.close();            } else {                path.moveTo((float) p1, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo(0, contentHeight);                path.lineTo(0, (float) p2);                path.close();            }            mCanvas.drawPath(path, ivisiblePaint);            canvas.drawBitmap(tmpBmp, 0, 0, null);        } public void drawLB(Canvas canvas) { double dx = contentWidth - scrollX, dy = contentHeight-scrollY; double len = Math.sqrt(dx * dx + dy * dy); if (len > contentWidth ) {                scrollX = (float) (contentWidth-contentWidth * dx /len);                scrollY = (float) (contentHeight-contentWidth * dy / len);            } double px = scrollX; double py = contentHeight - scrollY; double arc = 2 * Math.atan(py / px) * 180 / Math.PI;            Matrix m = new Matrix();            m.postTranslate(scrollX - contentWidth , scrollY - contentHeight);            m.postRotate((float) (-arc), scrollX, scrollY);            middlePage.draw(mCanvas);            Paint ps = new Paint();            Shader lg1 = new LinearGradient(contentWidth , contentHeight, contentWidth  - (float) px,                    contentHeight - (float) py, new int[] { 0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f,                            0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg1);            mCanvas.drawRect(0, 0, contentWidth, contentHeight, ps);            canvas.drawBitmap(tmpBmp, m, bmpPaint);            prevPage.draw(mCanvas);            Shader lg2 = new LinearGradient(scrollX, scrollY, 0, contentHeight, new int[] { 0x00000000, 0x33000000,                    0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg2);            mCanvas.drawRect(0, 0, contentWidth, contentHeight, ps);            arc = arc * Math.PI / 360;            Path path = new Path(); double r = Math.sqrt(px * px + py * py); double p1 = r / (2 * Math.cos(arc)); double p2 = r / (2 * Math.sin(arc));            Log.d(LOG_TAG, "p1: " + p1 + " p2:" + p2); if (arc == 0) {                path.moveTo((float) p1, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo((float) p1, contentHeight);                path.close();            } else if (p2 > contentHeight || p2 < 0) { double p3 = (p2 - contentHeight) * Math.tan(arc);                path.moveTo((float) p3, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo((float) p1, contentHeight);                path.close();            } else {                path.moveTo(0, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight);                path.lineTo((float) p1, contentHeight);                path.lineTo(0, contentHeight - (float) p2);                path.close();            }            mCanvas.drawPath(path, ivisiblePaint);            canvas.drawBitmap(tmpBmp, 0, 0, null);        } public void drawRT(Canvas canvas) { double dx = scrollX , dy = scrollY; double len = Math.sqrt(dx * dx + dy * dy); if (len > contentWidth) {                scrollX = (float) (contentWidth * dx /len);                scrollY = (float) (contentWidth * dy / len);            } double px = contentWidth - scrollX; double py = scrollY; double arc = 2 * Math.atan(py / px) * 180 / Math.PI;            Matrix m = new Matrix();            m.postTranslate(scrollX, scrollY);            m.postRotate((float) (-arc), scrollX, scrollY);            middlePage.draw(mCanvas);            Paint ps = new Paint();            Shader lg1 = new LinearGradient(0, 0, (float) px, (float) py, new int[] { 0x00000000, 0x33000000,                    0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg1);            mCanvas.drawRect(0, 0, contentWidth, contentHeight, ps);            canvas.drawBitmap(tmpBmp, m, bmpPaint);            nextPage.draw(mCanvas);            Shader lg2 = new LinearGradient(scrollX - contentWidth, scrollY, contentWidth, 0, new int[] {                    0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg2);            mCanvas.drawRect(0, 0, contentWidth, contentHeight, ps);            arc = arc * Math.PI / 360;            Path path = new Path(); double r = Math.sqrt(px * px + py * py); double p1 = contentWidth - r / (2 * Math.cos(arc)); double p2 = r / (2 * Math.sin(arc));            Log.d(LOG_TAG, "p1: " + p1 + " p2:" + p2); if (arc == 0) {                path.moveTo(0, 0);                path.lineTo((float) p1, 0);                path.lineTo((float) p1, contentHeight);                path.lineTo(0, contentHeight);                path.close();            } else if (p2 > contentHeight || p2 < 0) { double p3 = contentWidth  - (p2 - contentHeight) * Math.tan(arc);                path.moveTo(0, 0);                path.lineTo((float) p1, 0);                path.lineTo((float) p3, contentHeight);                path.lineTo(0, contentHeight);                path.close();            } else {                path.moveTo(0, 0);                path.lineTo((float) p1, 0);                path.lineTo(contentWidth , (float) p2);                path.lineTo(contentWidth , contentHeight);                path.lineTo(0, contentHeight);                path.close();            }            mCanvas.drawPath(path, ivisiblePaint);            canvas.drawBitmap(tmpBmp, 0 , 0, null);        } public void drawRB(Canvas canvas) { double dx = scrollX , dy = contentHeight - scrollY; double len = Math.sqrt(dx * dx + dy * dy); if (len > contentWidth ) {                scrollX = (float) (contentWidth * dx /len);                scrollY = (float) (contentHeight-contentWidth * dy / len);            } double px = contentWidth - scrollX; double py = contentHeight - scrollY; double arc = 2 * Math.atan(py / px) * 180 / Math.PI;            Matrix m = new Matrix();            m.postTranslate(scrollX, scrollY - contentHeight);            m.postRotate((float) (arc), scrollX, scrollY);            middlePage.draw(mCanvas);            Paint ps = new Paint();            Shader lg1 = new LinearGradient(0, contentHeight, (float) px, contentHeight - (float) py, new int[] {                    0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f }, Shader.TileMode.CLAMP);            ps.setShader(lg1);            mCanvas.drawRect(0, 0, contentWidth , contentHeight, ps);            canvas.drawBitmap(tmpBmp, m, bmpPaint);            nextPage.draw(mCanvas);            Shader lg2 = new LinearGradient(scrollX - contentWidth , scrollY, contentWidth , contentHeight, new int[] { 0x00000000, 0x33000000, 0x00000000 }, new float[] { 0.35f, 0.5f, 0.65f },                    Shader.TileMode.CLAMP);            ps.setShader(lg2);            mCanvas.drawRect(0, 0, contentWidth , contentHeight, ps);            arc = arc * Math.PI / 360;            Path path = new Path(); double r = Math.sqrt(px * px + py * py); double p1 = contentWidth  - r / (2 * Math.cos(arc)); double p2 = r / (2 * Math.sin(arc));            Log.d(LOG_TAG, "p1: " + p1 + " p2:" + p2); if (arc == 0) {                path.moveTo(0, 0);                path.lineTo((float) p1, 0);                path.lineTo((float) p1, contentHeight);                path.lineTo(0, contentHeight);                path.close();            } else if (p2 > contentHeight || p2 < 0) { double p3 = contentWidth  - (p2 - contentHeight) * Math.tan(arc);                path.moveTo(0, 0);                path.lineTo((float) p3, 0);                path.lineTo((float) p1, contentHeight);                path.lineTo(0, contentHeight);                path.close();            } else {                path.moveTo(0, 0);                path.lineTo(contentWidth , 0);                path.lineTo(contentWidth , contentHeight - (float) p2);                path.lineTo((float) p1, contentHeight);                path.lineTo(0, contentHeight);                path.close();            }            mCanvas.drawPath(path, ivisiblePaint);            canvas.drawBitmap(tmpBmp, 0 , 0, null);        } public void drawPrevPageEnd(Canvas canvas) {            prevPage.draw(mCanvas);            canvas.drawBitmap(tmpBmp, 0, 0, null);        } public void drawNextPageEnd(Canvas canvas) {            nextPage.draw(mCanvas);            canvas.drawBitmap(tmpBmp, contentWidth, 0, null);        } public void drawPage(Canvas canvas) { if (mSelectCorner == Corner.LeftTop) {                Log.d(LOG_TAG, "click left top");                drawLT(canvas);            } else if (mSelectCorner == Corner.LeftBottom) {                Log.d(LOG_TAG, "click left bottom");                drawLB(canvas);            } else if (mSelectCorner == Corner.RightTop) {                Log.d(LOG_TAG, "click right top");                drawRT(canvas);            } else if (mSelectCorner == Corner.RightBottom) {                Log.d(LOG_TAG, "click right bottom");                drawRB(canvas);            }        } public void update() {            Canvas canvas = surfaceHolder.lockCanvas(null); try { synchronized (surfaceHolder) {                    doDraw(canvas);                 }            } catch (Exception e) {                e.printStackTrace();             } finally { if (canvas != null) {                     surfaceHolder.unlockCanvasAndPost(canvas);                }            }        } protected void doDraw(Canvas canvas) {            Log.d(LOG_TAG, "bookView doDraw");            mainLayout.draw(canvas);        } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        } public void surfaceCreated(SurfaceHolder holder) {            update();        } public void surfaceDestroyed(SurfaceHolder holder) { if (dt != null) {                dt.flag = false;                 dt = null;             }        }    } public boolean getAnimateData() {        Log.d(LOG_TAG, "getAnimateData"); long time = aniTime;        Date date = new Date(); long t = date.getTime() - aniStartTime.getTime();        t += timeOffset; if (t < 0 || t > time) {            mState = BookState.ANIMATE_END; return false;        } else {            mState = BookState.ANIMATING; double sx = aniStopPos.x - aniStartPos.x;            scrollX =(float)(sx*t/time+aniStartPos.x); double sy = aniStopPos.y-aniStartPos.y;            scrollY = (float)(sy*t/time+aniStartPos.y); return true;        }    } public void handleAniEnd(Canvas canvas) {        Log.d(LOG_TAG, "handleAniEnd"); if (closeBook) {            closeBook = false; if (mSelectCorner == Corner.LeftTop || mSelectCorner == Corner.LeftBottom) { if (scrollX > contentWidth / 2) {                    indexPage -= 1;                    mBookView.drawPrevPageEnd(canvas);                    aniEndHandle.post(new Runnable() { public void run() {                            updatePageView();                        }                    });                } else {                    mBookView.doDraw(canvas);                }            } else if (mSelectCorner == Corner.RightTop || mSelectCorner == Corner.RightBottom) { if (scrollX < contentWidth / 2) {                    indexPage += 1;                    mBookView.drawNextPageEnd(canvas);                    aniEndHandle.post(new Runnable() { public void run() {                            updatePageView();                        }                    });                } else {                    mBookView.doDraw(canvas);                }            }            mSelectCorner = Corner.None;            mState = BookState.READY;        } else {            mState = BookState.TRACKING;        }        mBookView.stopAnimation(); // aniEndHandle.post(new Runnable() { // public void run() { //// BookLayout.this.invalidate(); // } // });  } class WhiteView extends View { public WhiteView(Context context) { super(context);        } protected void onDraw(Canvas canvas) { super.onDraw(canvas);            canvas.drawColor(Color.WHITE);        }    } public class DrawThread extends Thread {        BookView bv;         SurfaceHolder surfaceHolder; boolean flag = false; int sleepSpan = 30; public DrawThread(BookView bv, SurfaceHolder surfaceHolder) { this.bv = bv; this.surfaceHolder = surfaceHolder; this.flag = true;         } public void run() {            Canvas canvas = null; while (flag) { try {                    canvas = surfaceHolder.lockCanvas(null); if (canvas == null) continue; synchronized (surfaceHolder) { if (mState == BookState.ABOUT_TO_ANIMATE || mState == BookState.ANIMATING) {                            bv.doDraw(canvas);                            getAnimateData();                            bv.drawPage(canvas);                        } else if (mState == BookState.TRACKING) {                            bv.doDraw(canvas);                            bv.drawPage(canvas);                        } else if (mState == BookState.ANIMATE_END) {                            handleAniEnd(canvas);                        }                    }                } catch (Exception e) {                    e.printStackTrace();                 } finally { if (canvas != null) {                        surfaceHolder.unlockCanvasAndPost(canvas);                    }                } try {                    Thread.sleep(sleepSpan);                 } catch (Exception e) {                    e.printStackTrace();                 }            }        }    }}
复制代码

BookState:

package com.xin.book.view; public enum BookState {    ABOUT_TO_ANIMATE, ANIMATING, ANIMATE_END, READY, TRACKING}

Corner:

package com.xin.book.view; public enum Corner {    LeftTop, RightTop, LeftBottom, RightBottom, None}

IAdapter:

复制代码
package com.xin.book.view; import android.view.View; public interface IAdapter { public int getCount(); public String getItem(int position); public long getItemId(int position); public View getView(int position);}
复制代码

IBook:

复制代码
package com.xin.book.view; import android.view.View; public interface IBook { public View getView(int position); public int getCount();}
复制代码

IListener:

复制代码
package com.xin.book.view; public interface IListener { public void onPrevPage(); public void onNextPage(); public void onInit();}
复制代码

实例2效果图:

原文地址:http://www.cnblogs.com/hanyonglu/archive/2012/02/13/2348585.html

0 0
原创粉丝点击