| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
y37f
10年前发布

Android书籍翻页效果

模仿此效果,只需要 导入一下文件即可 :BookActivity.java,BookPageFactory.java,PageWidget.java

package com.andorid.shu.love;    import java.io.File;  import java.io.IOException;  import java.util.ArrayList;  import java.util.List;    import android.app.Activity;  import android.content.Context;  import android.database.Cursor;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.Canvas;  import android.os.Bundle;  import android.os.Environment;  import android.util.Log;  import android.view.Display;  import android.view.MotionEvent;  import android.view.View;  import android.view.View.OnTouchListener;  import android.widget.Toast;    import com.sqlite.DbHelper;    public class BookActivity extends Activity {   /** Called when the activity is first created. */   public final static int OPENMARK = 0;   public final static int SAVEMARK = 1;   public final static int TEXTSET = 2;      private PageWidget mPageWidget;   private Bitmap mCurPageBitmap, mNextPageBitmap;   private Canvas mCurPageCanvas, mNextPageCanvas;   private BookPageFactory pagefactory;   private static Boolean isExit = false;//用于判断是否推出   private static Boolean hasTask = false;   private int whichSize=6;//当前的字体大小   private int txtProgress = 0;//当前阅读的进度   private String txtPath = "/sdcard/lovereader/百年孤独.txt";   private String bookPath = "/sdcard/lovereader/";   final String[] font = new String[] {"20","24","26","30","32","36",     "40","46","50","56","60","66","70"};   int curPostion;   DbHelper db;    Context mContext;   Cursor mCursor;   BookInfo book = null;    SetupInfo setup = null;   //add for 2015-03-04   private int[] mPics = new int [] {R.drawable.c0,R.drawable.c1,R.drawable.c2,R.drawable.c3};   private int mCurrent = 0;   private int mNext = 1;   //add for 2015-03-06   private List<String> mFileList = new ArrayList<String>();   private static final String TAG = "BookActivity";   @Override   public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    /*requestWindowFeature(Window.FEATURE_NO_TITLE);    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,      WindowManager.LayoutParams.FLAG_FULLSCREEN);*/    Display display = getWindowManager().getDefaultDisplay();    int w = display.getWidth();    int h = display.getHeight();     System.out.println(w + "\t" + h);    BitmapFactory.Options options = new BitmapFactory.Options();      options.inSampleSize = 2;//图片大小,设置越大,图片越不清晰,占用空间越小     /*String SDPath = getSDPath();    Log.d(TAG, "sdPath:"+SDPath);*/    ///getFile(new File("/storage/extSdCard/pic/pic_1"));    //get FileDirPath    String dirPath = getIntent().getStringExtra("....");    dirPath = "/storage/extSdCard/pic/pic_1";    File mFile = new File(dirPath);    if(mFile.exists()){     if(mFile.isDirectory()){      if(mFile.listFiles().length==0){       Toast.makeText(this, "文件不存在!", Toast.LENGTH_SHORT).show();       return;      }     }    }    try {     //获取文件夹下的所有图片路径 填充mFileList集合     getFile(mFile);    } catch (IOException e2) {     // TODO Auto-generated catch block     e2.printStackTrace();    }    pagefactory = new BookPageFactory(w, h,mFileList);    mCurPageBitmap = BitmapFactory.decodeFile(mFileList.get(mCurrent), options);    mNextPageBitmap = BitmapFactory.decodeFile(mFileList.get(mNext), options);    mCurPageBitmap = pagefactory.resizePic(mCurPageBitmap, w, h);    mNextPageBitmap = pagefactory.resizePic(mNextPageBitmap, w, h);    mContext = this;    mPageWidget = new PageWidget(this, w, h);    setContentView(mPageWidget);    mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);    mPageWidget.setOnTouchListener(new OnTouchListener() {     @Override     public boolean onTouch(View v, MotionEvent e) {      boolean ret = false;      if (v == mPageWidget) {       if (e.getAction() == MotionEvent.ACTION_DOWN) {        mPageWidget.abortAnimation();        mPageWidget.calcCornerXY(e.getX(), e.getY());        //int temp = mCurrent!=0?mCurrent-1:0;        //获取当前页        mCurPageBitmap = pagefactory.getPage(mCurrent);        Log.d(TAG, "---当前页:mCurrentPic:"+mCurrent);        Log.d(TAG, "---当前页:路径:"+mFileList.get(mCurrent));        if (mPageWidget.DragToRight()) {         if (pagefactory.isfirstPage()){          Toast.makeText(mContext, "已经是第一页",Toast.LENGTH_SHORT).show();           return false;         }         //获取当前页坐标         mCurrent = mCurrent > 0?--mCurrent:0;         Log.d(TAG, "mCurrentPic:"+mCurrent);         mNextPageBitmap = pagefactory.prePage(mCurrent);         Log.d(TAG, "---下一页:路径:"+mFileList.get(mCurrent));        } else {         if (pagefactory.islastPage()){          Toast.makeText(mContext, "已经是最后一页",Toast.LENGTH_SHORT).show();          return false;         }         mCurrent = mCurrent < mFileList.size()-1 ?++mCurrent:mFileList.size()-1;         Log.d(TAG, "mCurrentPic:"+mCurrent);         Log.d(TAG, "---下一页:路径:"+mFileList.get(mCurrent));         mNextPageBitmap = pagefactory.nextPage(mCurrent);        }        mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);       }       ret = mPageWidget.doTouchEvent(e);       return ret;      }      return false;     }    });   }     public String getSDPath(){     File sdDir = null;     boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);   //判断sd卡是否存在     if(sdCardExist){                                    sdDir = Environment.getExternalStorageDirectory();//获取跟目录     }    return sdDir.toString();          }   /**    * 获取文件对象    * @param file    * @return    * @throws IOException     */   public List<String> getFile(File file) throws IOException{  //  Log.d(TAG, "getFile.fun..start..");    File[] fileArray =file.listFiles();  //  Log.d(TAG, "getFile.fun..listFiles..");    for (File f : fileArray) {  //   Log.d(TAG, "getFile.fun..ffff..");     if(f.isFile()){  //    Log.d(TAG, "getFile.fun..adddd..11111..");      mFileList.add(f.getCanonicalPath());  //    Log.d(TAG, "getFile.fun..adddd..");     }else{      getFile(f);  //    Log.d(TAG, "getFile.run..again..");     }    }  //  Log.d(TAG, "getFile.fun..finsh..");    return mFileList;   }  }

修改 BookActivity.java dirPath 路径即可

BookPageFactory.java

package com.andorid.shu.love;    import java.io.File;  import java.io.FileNotFoundException;  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.text.SimpleDateFormat;  import java.util.Date;  import java.util.List;  import java.util.Vector;    import android.content.res.Resources;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.Canvas;  import android.graphics.Color;  import android.graphics.Matrix;  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 = 50; //50   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 = 40;   private int r_fontSize = 30;   private int m_textColor = Color.BLACK;   private int m_backColor = 0xffff9e85; // 背景颜色   private int marginWidth = 15; // 左右与边缘的距离   private int marginHeight = 20; // 上下与边缘的距离   private int youmiHeight = 0;//广告条的狂度     private int mLineCount; // 每页可以显示的行数   private float mVisibleHeight; // 绘制内容的宽   private float mVisibleWidth; // 绘制内容的宽   private boolean m_isfirstPage, m_islastPage;   private int b_FontSize = 16;//底部文字大小   private int e_fontSize = 5;   private int spaceSize = 20;//行间距大小   private int curProgress = 0;//当前的进度   private String fileName = "";     // private int m_nLineSpaceing = 5;     private Paint mPaint;   private Paint bPaint;//底部文字绘制   private Paint spactPaint;//行间距绘制   private Paint titlePaint;//标题绘制   //add for 2015 03 06   private List<String> mFileList;//当前文件列表     public BookPageFactory(int w, int h,List<String> fileList) {    // TODO Auto-generated constructor stub    mWidth = w;    mHeight = h;    //add for 2015 03 04    this.mFileList = fileList;   }      //add for 2015 03 04   public Bitmap prePage(int currentNum){    this.m_islastPage = false;    if(currentNum == 0){     //currentNum = 0;     this.m_isfirstPage = true;    }else{     //currentNum--;     this.m_isfirstPage = false;    }    BitmapFactory.Options options = new BitmapFactory.Options();    options.inSampleSize = 2;//图片大小,设置越大,图片越不清晰,占用空间越小    Bitmap bitmap = BitmapFactory.decodeFile(mFileList.get(currentNum), options);    //Bitmap bitmap = BitmapFactory.decodeResource(this.mResources, mPics[currentNum]);    //图片放大至屏幕大小    bitmap = resizePic(bitmap, mWidth, mHeight);    return bitmap;   }      //add for 2015 03 04   public Bitmap nextPage(int currentNum){    this.m_isfirstPage = false;    if(currentNum >= mFileList.size()-1){     //currentNum = mPics.length-1;     this.m_islastPage = true;    }else{     //currentNum++;     this.m_islastPage = false;    }    BitmapFactory.Options options = new BitmapFactory.Options();    options.inSampleSize = 2;//图片大小,设置越大,图片越不清晰,占用空间越小    Bitmap bitmap = BitmapFactory.decodeFile(mFileList.get(currentNum), options);    //Bitmap bitmap = BitmapFactory.decodeResource(this.mResources, mPics[currentNum]);    //图片放大至屏幕大小    bitmap = resizePic(bitmap, mWidth, mHeight);    return bitmap;   }   //add for 2015 03 06   public Bitmap getPage(int currnet){    BitmapFactory.Options options = new BitmapFactory.Options();    options.inSampleSize = 2;//图片大小,设置越大,图片越不清晰,占用空间越小    Bitmap bitmap = BitmapFactory.decodeFile(mFileList.get(currnet), options);    //Bitmap bitmap = BitmapFactory.decodeResource(this.mResources, mPics[currnet]);    //图片放大至屏幕大小    bitmap = resizePic(bitmap, mWidth, mHeight);    return bitmap;   }   //add for 2015 03 06   public static Bitmap resizePic(Bitmap bitmap, int screenWidth,int screenHight) {       int w = bitmap.getWidth();       int h = bitmap.getHeight();       Matrix matrix = new Matrix();       float scale = (float) screenWidth / w;       float scale2 = (float) screenHight / h;       // scale = scale < scale2 ? scale : scale2;       matrix.postScale(scale, scale2);       Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);       if (bitmap != null && !bitmap.equals(bmp) && !bitmap.isRecycled()) {               bitmap.recycle();               bitmap = null;       }       return bmp;   }     private static double round1(double v, int scale) {    if (scale < 0)    return v;    String temp = "#####0.";    for (int i = 0; i < scale; i++) {    temp += "0";    }    return Double.valueOf(new java.text.DecimalFormat(temp).format(v));    }     public void setBgBitmap(Bitmap BG) {    if (BG.getWidth() != mWidth || BG.getHeight() != mHeight)     m_book_bg = Bitmap.createScaledBitmap(BG, mWidth, mHeight, true);    else     m_book_bg = BG;   }       public boolean isfirstPage() {    return m_isfirstPage;   }     public void setIslastPage(boolean islast){    m_islastPage = islast;   }   public boolean islastPage() {    return m_islastPage;   }    public int getCurPostion() {    return m_mbBufEnd;   }      public int getCurPostionBeg(){    return m_mbBufBegin;   }   public void setBeginPos(int pos) {    m_mbBufEnd = pos;    m_mbBufBegin = pos;   }      public int getBufLen() {    return m_mbBufLen;   }      public int getCurProgress(){    return curProgress;   }   public String getOneLine() {    return m_lines.toString().substring(0, 10);   }      public void changBackGround(int color) {    mPaint.setColor(color);   }      public void setFontSize(int size) {    m_fontSize = size;    mPaint.setTextSize(size);    int totalSize = m_fontSize+spaceSize;    mLineCount = (int) (mVisibleHeight / totalSize); // 可显示的行数   }      public void setFileName(String fileName){    fileName = fileName.substring(0,fileName.indexOf("."));    this.fileName = fileName;    }     }

PageWidget.java

package com.andorid.shu.love;    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, int w, int h) {    super(context);    // TODO Auto-generated constructor stub    mWidth = w;    mHeight = h;    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;   }    }

源代码下载地址