android酷炫翻页效果+图形分析

package  sf.hmg.turntest;

import  android.content.Context;
import  android.graphics.Bitmap;
import  android.graphics.Canvas;
import  android.graphics.ColorMatrix;
import  android.graphics.ColorMatrixColorFilter;
import  android.graphics.Matrix;
import  android.graphics.Paint;
import  android.graphics.Path;
import  android.graphics.PointF;
import  android.graphics.Region;
import  android.graphics.drawable.GradientDrawable;
import  android.view.MotionEvent;
import  android.view.View;
import  android.widget.Scroller;

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 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;
    ColorMatrixColorFilter mColorMatrixFilter;
    Matrix mMatrix;
    
float [] mMatrixArray  =  {  0 0 0 0 0 0 0 0 1.0f  };

    
boolean  mIsRTandLB;  //  是否属于右上左下
     float  mMaxLength  =  ( float ) Math.hypot(mWidth, mHeight);
    
int [] mBackShadowColors;
    
int [] mFrontShadowColors;
    GradientDrawable mBackShadowDrawableLR;
    GradientDrawable mBackShadowDrawableRL;
    GradientDrawable mFolderShadowDrawableLR;
    GradientDrawable mFolderShadowDrawableRL;

    GradientDrawable mFrontShadowDrawableHBT;
    GradientDrawable mFrontShadowDrawableHTB;
    GradientDrawable mFrontShadowDrawableVLR;
    GradientDrawable mFrontShadowDrawableVRL;

    Paint mPaint;

    Scroller mScroller;

    
public  PageWidget(Context context) {
        
super (context);
        
//  TODO Auto-generated constructor stub
        mPath0  =   new  Path();
        mPath1 
=   new  Path();
        createDrawable();

        mPaint 
=   new  Paint();
        mPaint.setStyle(Paint.Style.FILL);

        ColorMatrix cm 
=   new  ColorMatrix();
        
float  array[]  =  {  0.55f 0 0 0 80.0f 0 0.55f 0 0 80.0f 0 0 ,
                
0.55f 0 80.0f 0 0 0 0.2f 0  };
        cm.set(array);
        mColorMatrixFilter 
=   new  ColorMatrixColorFilter(cm);
        mMatrix 
=   new  Matrix();
        mScroller 
=   new  Scroller(getContext());

        mTouch.x 
=   0.01f //  不让x,y为0,否则在点计算时会有问题
        mTouch.y  =   0.01f ;
    }

    
/**
     * Author : hmg25 Version: 1.0 Description : 计算拖拽点对应的拖拽脚
     
*/
    
public   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 ;
    }

    
public   boolean  doTouchEvent(MotionEvent event) {
        
//  TODO Auto-generated method stub
         if  (event.getAction()  ==  MotionEvent.ACTION_MOVE) {
            mTouch.x 
=  event.getX();
            mTouch.y 
=  event.getY();
            
this .postInvalidate();
        }
        
if  (event.getAction()  ==  MotionEvent.ACTION_DOWN) {
            mTouch.x 
=  event.getX();
            mTouch.y 
=  event.getY();
            
//  calcCornerXY(mTouch.x, mTouch.y);
            
//  this.postInvalidate();
        }
        
if  (event.getAction()  ==  MotionEvent.ACTION_UP) {
            
if  (canDragOver()) {
                startAnimation(
1200 );
            } 
else  {
                mTouch.x 
=  mCornerX  -   0.09f ;
                mTouch.y 
=  mCornerY  -   0.09f ;
            }

            
this .postInvalidate();
        }
        
//  return super.onTouchEvent(event);
         return   true ;
    }

    
/**
     * Author : hmg25 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;

        
//  当mBezierStart1.x < 0或者mBezierStart1.x > 480时
        
//  如果继续翻页,会出现BUG故在此限制
         if  (mTouch.x  >   0   &&  mTouch.x  <  mWidth) {
            
if  (mBezierStart1.x  <   0   ||  mBezierStart1.x  >  mWidth) {
                
if  (mBezierStart1.x  <   0 )
                    mBezierStart1.x 
=  mWidth  -  mBezierStart1.x;

                
float  f1  =  Math.abs(mCornerX  -  mTouch.x);
                
float  f2  =  mWidth  *  f1  /  mBezierStart1.x;
                mTouch.x 
=  Math.abs(mCornerX  -  f2);

                
float  f3  =  Math.abs(mCornerX  -  mTouch.x)
                        
*  Math.abs(mCornerY  -  mTouch.y)  /  f1;
                mTouch.y 
=  Math.abs(mCornerY  -  f3);

                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 ;
            }
        }
        mBezierStart2.x 
=  mCornerX;
        mBezierStart2.y 
=  mBezierControl2.y  -  (mCornerY  -  mBezierControl2.y)
                
/   2 ;

        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 ;
    }

    
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));
        
int  leftx;
        
int  rightx;
        GradientDrawable mBackShadowDrawable;
        
if  (mIsRTandLB) {
            leftx 
=  ( int ) (mBezierStart1.x);
            rightx 
=  ( int ) (mBezierStart1.x  +  mTouchToCornerDis  /   4 );
            mBackShadowDrawable 
=  mBackShadowDrawableLR;
        } 
else  {
            leftx 
=  ( int ) (mBezierStart1.x  -  mTouchToCornerDis  /   4 );
            rightx 
=  ( int ) mBezierStart1.x;
            mBackShadowDrawable 
=  mBackShadowDrawableRL;
        }
        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) {
        mCurPageBitmap 
=  bm1;
        mNextPageBitmap 
=  bm2;
    }

    
public   void  setScreen( int  w,  int  h) {
        mWidth 
=  w;
        mHeight 
=  h;
    }

    @Override
    
protected   void  onDraw(Canvas canvas) {
        canvas.drawColor(
0xFFAAAAAA );
        calcPoints();
        drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);
        drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
        drawCurrentPageShadow(canvas);
        drawCurrentBackArea(canvas, mCurPageBitmap);
    }

    
/**
     * 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 [] {  0x80111111 0x111111  };
        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);
    }

    
/**
     * Author : hmg25 Version: 1.0 Description : 绘制翻起页的阴影
     
*/
    
public   void  drawCurrentPageShadow(Canvas canvas) {
        
double  degree;
        
if  (mIsRTandLB) {
            degree 
=  Math.PI
                    
/   4
                    
-  Math.atan2(mBezierControl1.y  -  mTouch.y, mTouch.x
                            
-  mBezierControl1.x);
        } 
else  {
            degree 
=  Math.PI
                    
/   4
                    
-  Math.atan2(mTouch.y  -  mBezierControl1.y, mTouch.x
                            
-  mBezierControl1.x);
        }
        
//  翻起页阴影顶点与touch点的距离
         double  d1  =  ( float 25   *   1.414   *  Math.cos(degree);
        
double  d2  =  ( float 25   *   1.414   *  Math.sin(degree);
        
float  x  =  ( float ) (mTouch.x  +  d1);
        
float  y;
        
if  (mIsRTandLB) {
            y 
=  ( float ) (mTouch.y  +  d2);
        } 
else  {
            y 
=  ( float ) (mTouch.y  -  d2);
        }
        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  +   1 ;
            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  -  mMaxLength), 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  +   1 );
            mCurrentPageShadow 
=  mFrontShadowDrawableHBT;
        }
        rotateDegrees 
=  ( float ) Math.toDegrees(Math.atan2(mBezierControl2.y
                
-  mTouch.y, mBezierControl2.x  -  mTouch.x));
        canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
        
float  temp;
        
if  (mBezierControl2.y  <   0 )
            temp 
=  mBezierControl2.y  -  mHeight;
        
else
            temp 
=  mBezierControl2.y;

        
int  hmg  =  ( int ) Math.hypot(mBezierControl2.x, temp);
        
if  (hmg  >  mMaxLength)
            mCurrentPageShadow
                    .setBounds((
int ) (mBezierControl2.x  -   25 -  hmg, leftx,
                            (
int ) (mBezierControl2.x  +  mMaxLength)  -  hmg,
                            rightx);
        
else
            mCurrentPageShadow.setBounds(
                    (
int ) (mBezierControl2.x  -  mMaxLength), leftx,
                    (
int ) (mBezierControl2.x), rightx);

        
//  Log.i("hmg", "mBezierControl2.x   " + mBezierControl2.x
        
//  + "  mBezierControl2.y  " + mBezierControl2.y);
        mCurrentPageShadow.draw(canvas);
        canvas.restore();
    }

    
/**
     * Author : hmg25 Version: 1.0 Description : 绘制翻起页背面
     
*/
    
private   void  drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
        
int  i  =  ( int ) (mBezierStart1.x  +  mBezierControl1.x)  /   2 ;
        
float  f1  =  Math.abs(i  -  mBezierControl1.x);
        
int  i1  =  ( int ) (mBezierStart2.y  +  mBezierControl2.y)  /   2 ;
        
float  f2  =  Math.abs(i1  -  mBezierControl2.y);
        
float  f3  =  Math.min(f1, f2);
        mPath1.reset();
        mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);
        mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
        mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
        mPath1.lineTo(mTouch.x, mTouch.y);
        mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
        mPath1.close();
        GradientDrawable mFolderShadowDrawable;
        
int  left;
        
int  right;
        
if  (mIsRTandLB) {
            left 
=  ( int ) (mBezierStart1.x  -   1 );
            right 
=  ( int ) (mBezierStart1.x  +  f3  +   1 );
            mFolderShadowDrawable 
=  mFolderShadowDrawableLR;
        } 
else  {
            left 
=  ( int ) (mBezierStart1.x  -  f3  -   1 );
            right 
=  ( int ) (mBezierStart1.x  +   1 );
            mFolderShadowDrawable 
=  mFolderShadowDrawableRL;
        }
        canvas.save();
        canvas.clipPath(mPath0);
        canvas.clipPath(mPath1, Region.Op.INTERSECT);

        mPaint.setColorFilter(mColorMatrixFilter);

        
float  dis  =  ( float ) Math.hypot(mCornerX  -  mBezierControl1.x,
                mBezierControl2.y 
-  mCornerY);
        
float  f8  =  (mCornerX  -  mBezierControl1.x)  /  dis;
        
float  f9  =  (mBezierControl2.y  -  mCornerY)  /  dis;
        mMatrixArray[
0 =   1   -   2   *  f9  *  f9;
        mMatrixArray[
1 =   2   *  f8  *  f9;
        mMatrixArray[
3 =  mMatrixArray[ 1 ];
        mMatrixArray[
4 =   1   -   2   *  f8  *  f8;
        mMatrix.reset();
        mMatrix.setValues(mMatrixArray);
        mMatrix.preTranslate(
- mBezierControl1.x,  - mBezierControl1.y);
        mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
        canvas.drawBitmap(bitmap, mMatrix, mPaint);
        
//  canvas.drawBitmap(bitmap, mMatrix, null);
        mPaint.setColorFilter( null );
        canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
        mFolderShadowDrawable.setBounds(left, (
int ) mBezierStart1.y, right,
                (
int ) (mBezierStart1.y  +  mMaxLength));
        mFolderShadowDrawable.draw(canvas);
        canvas.restore();
    }

    
public   void  computeScroll() {
        
super .computeScroll();
        
if  (mScroller.computeScrollOffset()) {
            
float  x  =  mScroller.getCurrX();
            
float  y  =  mScroller.getCurrY();
            mTouch.x 
=  x;
            mTouch.y 
=  y;
            postInvalidate();
        }
    }

    
private   void  startAnimation( int  delayMillis) {
        
int  dx, dy;
        
//  dx 水平方向滑动的距离,负值会使滚动向左滚动
        
//  dy 垂直方向滑动的距离,负值会使滚动向上滚动
         if  (mCornerX  >   0 ) {
            dx 
=   - ( int ) (mWidth  +  mTouch.x);
        } 
else  {
            dx 
=  ( int ) (mWidth  -  mTouch.x  +  mWidth);
        }
        
if  (mCornerY  >   0 ) {
            dy 
=  ( int ) (mHeight  -  mTouch.y);
        } 
else  {
            dy 
=  ( int ) ( 1   -  mTouch.y);  //  防止mTouch.y最终变为0
        }
        mScroller.startScroll((
int ) mTouch.x, ( int ) mTouch.y, dx, dy,
                delayMillis);
    }

    
public   void  abortAnimation() {
        
if  ( ! mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
    }

    
public   boolean  canDragOver() {
        
if  (mTouchToCornerDis  >  mWidth  /   10 )
            
return   true ;
        
return   false ;
    }

    
/**
     * Author : hmg25 Version: 1.0 Description : 是否从左边翻向右边
     
*/
    
public   boolean  DragToRight() {
        
if  (mCornerX  >   0 )
            
return   false ;
        
return   true ;
    }

}

/**
 *  Author :  hmg25
 *  Description :
 
*/
package  sf.hmg.turntest;

import  java.io.File;
import  java.io.IOException;
import  java.io.RandomAccessFile;
import  java.io.UnsupportedEncodingException;
import  java.nio.MappedByteBuffer;
import  java.nio.channels.FileChannel;
import  java.text.DecimalFormat;
import  java.util.Vector;

import  android.graphics.Bitmap;
import  android.graphics.Canvas;
import  android.graphics.Color;
import  android.graphics.Paint;
import  android.graphics.Paint.Align;

public   class  BookPageFactory {

    
private  File book_file  =   null ;
    
private  MappedByteBuffer m_mbBuf  =   null ;
    
private   int  m_mbBufLen  =   0 ;
    
private   int  m_mbBufBegin  =   0 ;
    
private   int  m_mbBufEnd  =   0 ;
    
private  String m_strCharsetName  =   " GBK " ;
    
private  Bitmap m_book_bg  =   null ;
    
private   int  mWidth;
    
private   int  mHeight;

    
private  Vector < String >  m_lines  =   new  Vector < String > ();

    
private   int  m_fontSize  =   24 ;
    
private   int  m_textColor  =  Color.BLACK;
    
private   int  m_backColor  =   0xffff9e85 //  背景颜色
     private   int  marginWidth  =   15 //  左右与边缘的距离
     private   int  marginHeight  =   20 //  上下与边缘的距离

    
private   int  mLineCount;  //  每页可以显示的行数
     private   float  mVisibleHeight;  //  绘制内容的宽
     private   float  mVisibleWidth;  //  绘制内容的宽
     private   boolean  m_isfirstPage,m_islastPage;

    
//  private int m_nLineSpaceing = 5;

    
private  Paint mPaint;

    
public  BookPageFactory( int  w,  int  h) {
        
//  TODO Auto-generated constructor stub
        mWidth  =  w;
        mHeight 
=  h;
        mPaint 
=   new  Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextAlign(Align.LEFT);
        mPaint.setTextSize(m_fontSize);
        mPaint.setColor(m_textColor);
        mVisibleWidth 
=  mWidth  -  marginWidth  *   2 ;
        mVisibleHeight 
=  mHeight  -  marginHeight  *   2 ;
        mLineCount 
=  ( int ) (mVisibleHeight  /  m_fontSize);  //  可显示的行数
    }

    
public   void  openbook(String strFilePath)  throws  IOException {
        book_file 
=   new  File(strFilePath);
        
long  lLen  =  book_file.length();
        m_mbBufLen 
=  ( int ) lLen;
        m_mbBuf 
=   new  RandomAccessFile(book_file,  " r " ).getChannel().map(
                FileChannel.MapMode.READ_ONLY, 
0 , lLen);
    }
    

    
protected   byte [] readParagraphBack( int  nFromPos) {
        
int  nEnd  =  nFromPos;
        
int  i;
        
byte  b0, b1;
        
if  (m_strCharsetName.equals( " UTF-16LE " )) {
            i 
=  nEnd  -   2 ;
            
while  (i  >   0 ) {
                b0 
=  m_mbBuf.get(i);
                b1 
=  m_mbBuf.get(i  +   1 );
                
if  (b0  ==   0x0a   &&  b1  ==   0x00   &&  i  !=  nEnd  -   2 ) {
                    i 
+=   2 ;
                    
break ;
                }
                i
-- ;
            }

        } 
else   if  (m_strCharsetName.equals( " UTF-16BE " )) {
            i 
=  nEnd  -   2 ;
            
while  (i  >   0 ) {
                b0 
=  m_mbBuf.get(i);
                b1 
=  m_mbBuf.get(i  +   1 );
                
if  (b0  ==   0x00   &&  b1  ==   0x0a   &&  i  !=  nEnd  -   2 ) {
                    i 
+=   2 ;
                    
break ;
                }
                i
-- ;
            }
        } 
else  {
            i 
=  nEnd  -   1 ;
            
while  (i  >   0 ) {
                b0 
=  m_mbBuf.get(i);
                
if  (b0  ==   0x0a   &&  i  !=  nEnd  -   1 ) {
                    i
++ ;
                    
break ;
                }
                i
-- ;
            }
        }
        
if  (i  <   0 )
            i 
=   0 ;
        
int  nParaSize  =  nEnd  -  i;
        
int  j;
        
byte [] buf  =   new   byte [nParaSize];
        
for  (j  =   0 ; j  <  nParaSize; j ++ ) {
            buf[j] 
=  m_mbBuf.get(i  +  j);
        }
        
return  buf;
    }


    
//  读取上一段落
     protected   byte [] readParagraphForward( int  nFromPos) {
        
int  nStart  =  nFromPos;
        
int  i  =  nStart;
        
byte  b0, b1;
        
//  根据编码格式判断换行
         if  (m_strCharsetName.equals( " UTF-16LE " )) {
            
while  (i  <  m_mbBufLen  -   1 ) {
                b0 
=  m_mbBuf.get(i ++ );
                b1 
=  m_mbBuf.get(i ++ );
                
if  (b0  ==   0x0a   &&  b1  ==   0x00 ) {
                    
break ;
                }
            }
        } 
else   if  (m_strCharsetName.equals( " UTF-16BE " )) {
            
while  (i  <  m_mbBufLen  -   1 ) {
                b0 
=  m_mbBuf.get(i ++ );
                b1 
=  m_mbBuf.get(i ++ );
                
if  (b0  ==   0x00   &&  b1  ==   0x0a ) {
                    
break ;
                }
            }
        } 
else  {
            
while  (i  <  m_mbBufLen) {
                b0 
=  m_mbBuf.get(i ++ );
                
if  (b0  ==   0x0a ) {
                    
break ;
                }
            }
        }
        
int  nParaSize  =  i  -  nStart;
        
byte [] buf  =   new   byte [nParaSize];
        
for  (i  =   0 ; i  <  nParaSize; i ++ ) {
            buf[i] 
=  m_mbBuf.get(nFromPos  +  i);
        }
        
return  buf;
    }

    
protected  Vector < String >  pageDown() {
        String strParagraph 
=   "" ;
        Vector
< String >  lines  =   new  Vector < String > ();
        
while  (lines.size()  <  mLineCount  &&  m_mbBufEnd  <  m_mbBufLen) {
            
byte [] paraBuf  =  readParagraphForward(m_mbBufEnd);  //  读取一个段落
            m_mbBufEnd  +=  paraBuf.length;
            
try  {
                strParagraph 
=   new  String(paraBuf, m_strCharsetName);
            } 
catch  (UnsupportedEncodingException e) {
                
//  TODO Auto-generated catch block
                e.printStackTrace();
            }
            String strReturn 
=   "" ;
            
if  (strParagraph.indexOf( " \r\n " !=   - 1 ) {
                strReturn 
=   " \r\n " ;
                strParagraph 
=  strParagraph.replaceAll( " \r\n " "" );
            } 
else   if  (strParagraph.indexOf( " \n " !=   - 1 ) {
                strReturn 
=   " \n " ;
                strParagraph 
=  strParagraph.replaceAll( " \n " "" );
            }

            
if  (strParagraph.length()  ==   0 ) {
                lines.add(strParagraph);
            }
            
while  (strParagraph.length()  >   0 ) {
                
int  nSize  =  mPaint.breakText(strParagraph,  true , mVisibleWidth,
                        
null );
                lines.add(strParagraph.substring(
0 , nSize));
                strParagraph 
=  strParagraph.substring(nSize);
                
if  (lines.size()  >=  mLineCount) {
                    
break ;
                }
            }
            
if  (strParagraph.length()  !=   0 ) {
                
try  {
                    m_mbBufEnd 
-=  (strParagraph  +  strReturn)
                            .getBytes(m_strCharsetName).length;
                } 
catch  (UnsupportedEncodingException e) {
                    
//  TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
return  lines;
    }

    
protected   void  pageUp() {
        
if  (m_mbBufBegin  <   0 )
            m_mbBufBegin 
=   0 ;
        Vector
< String >  lines  =   new  Vector < String > ();
        String strParagraph 
=   "" ;
        
while  (lines.size()  <  mLineCount  &&  m_mbBufBegin  >   0 ) {
            Vector
< String >  paraLines  =   new  Vector < String > ();
            
byte [] paraBuf  =  readParagraphBack(m_mbBufBegin);
            m_mbBufBegin 
-=  paraBuf.length;
            
try  {
                strParagraph 
=   new  String(paraBuf, m_strCharsetName);
            } 
catch  (UnsupportedEncodingException e) {
                
//  TODO Auto-generated catch block
                e.printStackTrace();
            }
            strParagraph 
=  strParagraph.replaceAll( " \r\n " "" );
            strParagraph 
=  strParagraph.replaceAll( " \n " "" );

            
if  (strParagraph.length()  ==   0 ) {
                paraLines.add(strParagraph);
            }
            
while  (strParagraph.length()  >   0 ) {
                
int  nSize  =  mPaint.breakText(strParagraph,  true , mVisibleWidth,
                        
null );
                paraLines.add(strParagraph.substring(
0 , nSize));
                strParagraph 
=  strParagraph.substring(nSize);
            }
            lines.addAll(
0 , paraLines);
        }
        
while  (lines.size()  >  mLineCount) {
            
try  {
                m_mbBufBegin 
+=  lines.get( 0 ).getBytes(m_strCharsetName).length;
                lines.remove(
0 );
            } 
catch  (UnsupportedEncodingException e) {
                
//  TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        m_mbBufEnd 
=  m_mbBufBegin;
        
return ;
    }

    
protected   void  prePage()  throws  IOException {
        
if  (m_mbBufBegin  <=   0 ) {
            m_mbBufBegin 
=   0 ;
            m_isfirstPage
= true ;
            
return ;
        }
else  m_isfirstPage = false ;
        m_lines.clear();
        pageUp();
        m_lines 
=  pageDown();
    }

    
public   void  nextPage()  throws  IOException {
        
if  (m_mbBufEnd  >=  m_mbBufLen) {
            m_islastPage
= true ;
            
return ;
        }
else  m_islastPage = false ;
        m_lines.clear();
        m_mbBufBegin 
=  m_mbBufEnd;
        m_lines 
=  pageDown();
    }

    
public   void  onDraw(Canvas c) {
        
if  (m_lines.size()  ==   0 )
            m_lines 
=  pageDown();
        
if  (m_lines.size()  >   0 ) {
            
if  (m_book_bg  ==   null )
                c.drawColor(m_backColor);
            
else
                c.drawBitmap(m_book_bg, 
0 0 null );
            
int  y  =  marginHeight;
            
for  (String strLine : m_lines) {
                y 
+=  m_fontSize;
                c.drawText(strLine, marginWidth, y, mPaint);
            }
        }
        
float  fPercent  =  ( float ) (m_mbBufBegin  *   1.0   /  m_mbBufLen);
        DecimalFormat df 
=   new  DecimalFormat( " #0.0 " );
        String strPercent 
=  df.format(fPercent  *   100 +   " % " ;
        
int  nPercentWidth  =  ( int ) mPaint.measureText( " 999.9% " +   1 ;
        c.drawText(strPercent, mWidth 
-  nPercentWidth, mHeight  -   5 , mPaint);
    }

    
public   void  setBgBitmap(Bitmap BG) {
        m_book_bg 
=  BG;
    }
    
    
public   boolean  isfirstPage() {
        
return  m_isfirstPage;
    }
    
public   boolean  islastPage() {
        
return  m_islastPage;
    }
}

package  sf.hmg.turntest;

import  java.io.IOException;

import  android.app.Activity;
import  android.graphics.Bitmap;
import  android.graphics.BitmapFactory;
import  android.graphics.Canvas;
import  android.graphics.Paint;
import  android.os.Bundle;
import  android.view.MotionEvent;
import  android.view.View;
import  android.view.View.OnTouchListener;
import  android.view.Window;
import  android.view.WindowManager;
import  android.widget.Toast;

public   class  turntest  extends  Activity {
    
/**  Called when the activity is first created.  */
    
private  PageWidget mPageWidget;
    Bitmap mCurPageBitmap, mNextPageBitmap;
    Canvas mCurPageCanvas, mNextPageCanvas;
    BookPageFactory pagefactory;

    @Override
    
public   void  onCreate(Bundle savedInstanceState) {
        
super .onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        mPageWidget 
=   new  PageWidget( this );
        setContentView(mPageWidget);

        mCurPageBitmap 
=  Bitmap.createBitmap( 480 800 , Bitmap.Config.ARGB_8888);
        mNextPageBitmap 
=  Bitmap
                .createBitmap(
480 800 , Bitmap.Config.ARGB_8888);

        mCurPageCanvas 
=   new  Canvas(mCurPageBitmap);
        mNextPageCanvas 
=   new  Canvas(mNextPageBitmap);
        pagefactory 
=   new  BookPageFactory( 480 800 );

        pagefactory.setBgBitmap(BitmapFactory.decodeResource(
                
this .getResources(), R.drawable.bg));

        
try  {
            pagefactory.openbook(
" /sdcard/test.txt " );
            pagefactory.onDraw(mCurPageCanvas);
        } 
catch  (IOException e1) {
            
//  TODO Auto-generated catch block
            e1.printStackTrace();
            Toast.makeText(
this " 电子书不存在,请将《test.txt》放在SD卡根目录下 " ,
                    Toast.LENGTH_SHORT).show();
        }

        mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);

        mPageWidget.setOnTouchListener(
new  OnTouchListener() {
            @Override
            
public   boolean  onTouch(View v, MotionEvent e) {
                
//  TODO Auto-generated method stub
                
                
boolean  ret = false ;
                
if  (v  ==  mPageWidget) {
                    
if  (e.getAction()  ==  MotionEvent.ACTION_DOWN) {
                        mPageWidget.abortAnimation();
                        mPageWidget.calcCornerXY(e.getX(), e.getY());

                        pagefactory.onDraw(mCurPageCanvas);
                        
if  (mPageWidget.DragToRight()) {
                            
try  {
                                pagefactory.prePage();
                            } 
catch  (IOException e1) {
                                
//  TODO Auto-generated catch block
                                e1.printStackTrace();
                            }                        
                            
if (pagefactory.isfirstPage()) return   false ;
                            pagefactory.onDraw(mNextPageCanvas);
                        } 
else  {
                            
try  {
                                pagefactory.nextPage();
                            } 
catch  (IOException e1) {
                                
//  TODO Auto-generated catch block
                                e1.printStackTrace();
                            }
                            
if (pagefactory.islastPage()) return   false ;
                            pagefactory.onDraw(mNextPageCanvas);
                        }
                        mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
                    }
                 
                     ret 
=  mPageWidget.doTouchEvent(e);
                    
return  ret;
                }
                
return   false ;
            }

        });
    }
}

更多相关文章

  1. Android触控事件
  2. android中的坐标系以及获取坐标的方法
  3. RelativeLayout 相对布局属性
  4. android:layout_marginLeft等的简单用法
  5. 相对布局常用属性介绍(RelativeLayout)
  6. Android(安卓)OpenGL ES 开发教程 从入门到精通
  7. Android使用AchartEngine绘制曲线图
  8. Android显示原理
  9. 线性布局控件间的布局设置

随机推荐

  1. cocos2dx 在mac下开发ios和android游戏
  2. Android(安卓)Studio打包apk
  3. android PowerManager wakelock
  4. android 混淆文件proguard.cfg详解
  5. 个人收集的Android开发相关网站集
  6. Android开发中调用系统设置界面
  7. Android(安卓)资料整理
  8. Android(安卓)之 SharedPreferences
  9. Data Binding的报错集合: 例如Error:(10,
  10. Android仿ios微信左划条目删除、置顶的实