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

        });
    }
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值