類似Ireader的看書軟件源碼

首先申明一點,翻書的效果不是我本人寫的,我只是優化一下加載文件和其它小東東!

 

先看圖吧!

 

 

 

源碼部分:

 

  1. package com.book.lee;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7.   
  8. import android.app.Activity;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.BitmapFactory;  
  11. import android.graphics.Canvas;  
  12. import android.os.Bundle;  
  13. import android.view.Display;  
  14. import android.view.MotionEvent;  
  15. import android.view.View;  
  16. import android.view.View.OnTouchListener;  
  17. import android.view.Window;  
  18. import android.view.WindowManager;  
  19. import android.widget.Toast;  
  20.   
  21. public class BookActivity extends Activity {  
  22.     /** Called when the activity is first created. */  
  23.     private PageWidget mPageWidget;  
  24.     private Bitmap mCurPageBitmap, mNextPageBitmap;  
  25.     private Canvas mCurPageCanvas, mNextPageCanvas;  
  26.     private BookPageFactory pagefactory;  
  27.   
  28.     @Override  
  29.     public void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  32.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  33.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  34.   
  35.         Display display = getWindowManager().getDefaultDisplay();  
  36.         int w = display.getWidth();  
  37.         int h = display.getHeight();  
  38.         System.out.println(w + "\t" + h);  
  39.         mCurPageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);  
  40.         mNextPageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);  
  41.   
  42.         mCurPageCanvas = new Canvas(mCurPageBitmap);  
  43.         mNextPageCanvas = new Canvas(mNextPageBitmap);  
  44.         pagefactory = new BookPageFactory(w, h);  
  45.   
  46.         pagefactory.setBgBitmap(BitmapFactory.decodeResource(getResources(),  
  47.                 R.drawable.bg));  
  48.         if (!copyFile()) {  
  49.             Toast.makeText(this"電子書不存在!", Toast.LENGTH_SHORT).show();  
  50.         } else {  
  51.             pagefactory.openbook("/sdcard/test.txt");  
  52.             pagefactory.onDraw(mCurPageCanvas);  
  53.         }  
  54.   
  55.         mPageWidget = new PageWidget(this, w, h);  
  56.         setContentView(mPageWidget);  
  57.         mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);  
  58.   
  59.         mPageWidget.setOnTouchListener(new OnTouchListener() {  
  60.             @Override  
  61.             public boolean onTouch(View v, MotionEvent e) {  
  62.                 // TODO Auto-generated method stub  
  63.   
  64.                 boolean ret = false;  
  65.                 if (v == mPageWidget) {  
  66.                     if (e.getAction() == MotionEvent.ACTION_DOWN) {  
  67.                         mPageWidget.abortAnimation();  
  68.                         mPageWidget.calcCornerXY(e.getX(), e.getY());  
  69.   
  70.                         pagefactory.onDraw(mCurPageCanvas);  
  71.                         if (mPageWidget.DragToRight()) {  
  72.                             try {  
  73.                                 pagefactory.prePage();  
  74.                             } catch (IOException e1) {  
  75.                                 // TODO Auto-generated catch block  
  76.                                 e1.printStackTrace();  
  77.                             }  
  78.                             if (pagefactory.isfirstPage())  
  79.                                 return false;  
  80.                             pagefactory.onDraw(mNextPageCanvas);  
  81.                         } else {  
  82.                             try {  
  83.                                 pagefactory.nextPage();  
  84.                             } catch (IOException e1) {  
  85.                                 // TODO Auto-generated catch block  
  86.                                 e1.printStackTrace();  
  87.                             }  
  88.                             if (pagefactory.islastPage())  
  89.                                 return false;  
  90.                             pagefactory.onDraw(mNextPageCanvas);  
  91.                         }  
  92.                         mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);  
  93.                     }  
  94.   
  95.                     ret = mPageWidget.doTouchEvent(e);  
  96.                     return ret;  
  97.                 }  
  98.                 return false;  
  99.             }  
  100.   
  101.         });  
  102.     }  
  103.   
  104.     protected boolean copyFile() {  
  105.         try {  
  106.             String dst = "/sdcard/test.txt";  
  107.             File outFile = new File(dst);  
  108.             if (!outFile.exists()) {  
  109.                 InputStream inStream = getResources().openRawResource(  
  110.                         R.raw.test);  
  111.                 outFile.createNewFile();  
  112.                 FileOutputStream fs = new FileOutputStream(outFile);  
  113.                 byte[] buffer = new byte[1024 * 1024];// 1MB  
  114.                 int byteread = 0;  
  115.                 while ((byteread = inStream.read(buffer)) != -1) {  
  116.                     fs.write(buffer, 0, byteread);  
  117.                 }  
  118.                 inStream.close();  
  119.                 fs.close();  
  120.             }  
  121.             return true;  
  122.         } catch (Exception e) {  
  123.             e.printStackTrace();  
  124.         }  
  125.         return false;  
  126.     }  
  127.   
  128. }  


 

  1. /** 
  2.  *  Author :  hmg25 
  3.  *  Description : 
  4.  */  
  5. package com.book.lee;  
  6.   
  7. import java.io.File;  
  8. import java.io.FileNotFoundException;  
  9. import java.io.IOException;  
  10. import java.io.RandomAccessFile;  
  11. import java.io.UnsupportedEncodingException;  
  12. import java.nio.MappedByteBuffer;  
  13. import java.nio.channels.FileChannel;  
  14. import java.text.DecimalFormat;  
  15. import java.util.Vector;  
  16.   
  17. import android.graphics.Bitmap;  
  18. import android.graphics.Canvas;  
  19. import android.graphics.Color;  
  20. import android.graphics.Paint;  
  21. import android.graphics.Paint.Align;  
  22.   
  23. public class BookPageFactory {  
  24.   
  25.     private File book_file = null;  
  26.     private MappedByteBuffer m_mbBuf = null;  
  27.     private int m_mbBufLen = 0;  
  28.     private int m_mbBufBegin = 0;  
  29.     private int m_mbBufEnd = 0;  
  30.     private String m_strCharsetName = "GBK";  
  31.     private Bitmap m_book_bg = null;  
  32.     private int mWidth;  
  33.     private int mHeight;  
  34.   
  35.     private Vector<String> m_lines = new Vector<String>();  
  36.   
  37.     private int m_fontSize = 24;  
  38.     private int m_textColor = Color.BLACK;  
  39.     private int m_backColor = 0xffff9e85// 背景顏色  
  40.     private int marginWidth = 15// 左右與邊緣的距離  
  41.     private int marginHeight = 20// 上下與邊緣的距離  
  42.   
  43.     private int mLineCount; // 每頁可以顯示的行數  
  44.     private float mVisibleHeight; // 繪製內容的寬  
  45.     private float mVisibleWidth; // 繪製內容的寬  
  46.     private boolean m_isfirstPage, m_islastPage;  
  47.   
  48.     // private int m_nLineSpaceing = 5;  
  49.   
  50.     private Paint mPaint;  
  51.   
  52.     public BookPageFactory(int w, int h) {  
  53.         // TODO Auto-generated constructor stub  
  54.         mWidth = w;  
  55.         mHeight = h;  
  56.         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  57.         mPaint.setTextAlign(Align.LEFT);  
  58.         mPaint.setTextSize(m_fontSize);  
  59.         mPaint.setColor(m_textColor);  
  60.         mVisibleWidth = mWidth - marginWidth * 2;  
  61.         mVisibleHeight = mHeight - marginHeight * 2;  
  62.         mLineCount = (int) (mVisibleHeight / m_fontSize); // 可顯示的行數  
  63.     }  
  64.   
  65.     public void openbook(String strFilePath) {  
  66.         try {  
  67.             book_file = new File(strFilePath);  
  68.             long lLen = book_file.length();  
  69.             m_mbBufLen = (int) lLen;  
  70.             m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map(  
  71.                     FileChannel.MapMode.READ_ONLY, 0, lLen);  
  72.         } catch (FileNotFoundException e) {  
  73.             // TODO Auto-generated catch block  
  74.             e.printStackTrace();  
  75.         } catch (IOException e) {  
  76.             // TODO Auto-generated catch block  
  77.             e.printStackTrace();  
  78.         }  
  79.     }  
  80.   
  81.     protected byte[] readParagraphBack(int nFromPos) {  
  82.         int nEnd = nFromPos;  
  83.         int i;  
  84.         byte b0, b1;  
  85.         if (m_strCharsetName.equals("UTF-16LE")) {  
  86.             i = nEnd - 2;  
  87.             while (i > 0) {  
  88.                 b0 = m_mbBuf.get(i);  
  89.                 b1 = m_mbBuf.get(i + 1);  
  90.                 if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2) {  
  91.                     i += 2;  
  92.                     break;  
  93.                 }  
  94.                 i--;  
  95.             }  
  96.   
  97.         } else if (m_strCharsetName.equals("UTF-16BE")) {  
  98.             i = nEnd - 2;  
  99.             while (i > 0) {  
  100.                 b0 = m_mbBuf.get(i);  
  101.                 b1 = m_mbBuf.get(i + 1);  
  102.                 if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2) {  
  103.                     i += 2;  
  104.                     break;  
  105.                 }  
  106.                 i--;  
  107.             }  
  108.         } else {  
  109.             i = nEnd - 1;  
  110.             while (i > 0) {  
  111.                 b0 = m_mbBuf.get(i);  
  112.                 if (b0 == 0x0a && i != nEnd - 1) {  
  113.                     i++;  
  114.                     break;  
  115.                 }  
  116.                 i--;  
  117.             }  
  118.         }  
  119.         if (i < 0)  
  120.             i = 0;  
  121.         int nParaSize = nEnd - i;  
  122.         int j;  
  123.         byte[] buf = new byte[nParaSize];  
  124.         for (j = 0; j < nParaSize; j++) {  
  125.             buf[j] = m_mbBuf.get(i + j);  
  126.         }  
  127.         return buf;  
  128.     }  
  129.   
  130.     // 讀取上一段落  
  131.     protected byte[] readParagraphForward(int nFromPos) {  
  132.         int nStart = nFromPos;  
  133.         int i = nStart;  
  134.         byte b0, b1;  
  135.         // 根據編碼格式判斷換行  
  136.         if (m_strCharsetName.equals("UTF-16LE")) {  
  137.             while (i < m_mbBufLen - 1) {  
  138.                 b0 = m_mbBuf.get(i++);  
  139.                 b1 = m_mbBuf.get(i++);  
  140.                 if (b0 == 0x0a && b1 == 0x00) {  
  141.                     break;  
  142.                 }  
  143.             }  
  144.         } else if (m_strCharsetName.equals("UTF-16BE")) {  
  145.             while (i < m_mbBufLen - 1) {  
  146.                 b0 = m_mbBuf.get(i++);  
  147.                 b1 = m_mbBuf.get(i++);  
  148.                 if (b0 == 0x00 && b1 == 0x0a) {  
  149.                     break;  
  150.                 }  
  151.             }  
  152.         } else {  
  153.             while (i < m_mbBufLen) {  
  154.                 b0 = m_mbBuf.get(i++);  
  155.                 if (b0 == 0x0a) {  
  156.                     break;  
  157.                 }  
  158.             }  
  159.         }  
  160.         int nParaSize = i - nStart;  
  161.         byte[] buf = new byte[nParaSize];  
  162.         for (i = 0; i < nParaSize; i++) {  
  163.             buf[i] = m_mbBuf.get(nFromPos + i);  
  164.         }  
  165.         return buf;  
  166.     }  
  167.   
  168.     protected Vector<String> pageDown() {  
  169.         String strParagraph = "";  
  170.         Vector<String> lines = new Vector<String>();  
  171.         while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen) {  
  172.             byte[] paraBuf = readParagraphForward(m_mbBufEnd); // 讀取一個段落  
  173.             m_mbBufEnd += paraBuf.length;  
  174.             try {  
  175.                 strParagraph = new String(paraBuf, m_strCharsetName);  
  176.             } catch (UnsupportedEncodingException e) {  
  177.                 // TODO Auto-generated catch block  
  178.                 e.printStackTrace();  
  179.             }  
  180.             String strReturn = "";  
  181.             if (strParagraph.indexOf("\r\n") != -1) {  
  182.                 strReturn = "\r\n";  
  183.                 strParagraph = strParagraph.replaceAll("\r\n""");  
  184.             } else if (strParagraph.indexOf("\n") != -1) {  
  185.                 strReturn = "\n";  
  186.                 strParagraph = strParagraph.replaceAll("\n""");  
  187.             }  
  188.   
  189.             if (strParagraph.length() == 0) {  
  190.                 lines.add(strParagraph);  
  191.             }  
  192.             while (strParagraph.length() > 0) {  
  193.                 int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,  
  194.                         null);  
  195.                 lines.add(strParagraph.substring(0, nSize));  
  196.                 strParagraph = strParagraph.substring(nSize);  
  197.                 if (lines.size() >= mLineCount) {  
  198.                     break;  
  199.                 }  
  200.             }  
  201.             if (strParagraph.length() != 0) {  
  202.                 try {  
  203.                     m_mbBufEnd -= (strParagraph + strReturn)  
  204.                             .getBytes(m_strCharsetName).length;  
  205.                 } catch (UnsupportedEncodingException e) {  
  206.                     // TODO Auto-generated catch block  
  207.                     e.printStackTrace();  
  208.                 }  
  209.             }  
  210.         }  
  211.         return lines;  
  212.     }  
  213.   
  214.     protected void pageUp() {  
  215.         if (m_mbBufBegin < 0)  
  216.             m_mbBufBegin = 0;  
  217.         Vector<String> lines = new Vector<String>();  
  218.         String strParagraph = "";  
  219.         while (lines.size() < mLineCount && m_mbBufBegin > 0) {  
  220.             Vector<String> paraLines = new Vector<String>();  
  221.             byte[] paraBuf = readParagraphBack(m_mbBufBegin);  
  222.             m_mbBufBegin -= paraBuf.length;  
  223.             try {  
  224.                 strParagraph = new String(paraBuf, m_strCharsetName);  
  225.             } catch (UnsupportedEncodingException e) {  
  226.                 // TODO Auto-generated catch block  
  227.                 e.printStackTrace();  
  228.             }  
  229.             strParagraph = strParagraph.replaceAll("\r\n""");  
  230.             strParagraph = strParagraph.replaceAll("\n""");  
  231.   
  232.             if (strParagraph.length() == 0) {  
  233.                 paraLines.add(strParagraph);  
  234.             }  
  235.             while (strParagraph.length() > 0) {  
  236.                 int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,  
  237.                         null);  
  238.                 paraLines.add(strParagraph.substring(0, nSize));  
  239.                 strParagraph = strParagraph.substring(nSize);  
  240.             }  
  241.             lines.addAll(0, paraLines);  
  242.         }  
  243.         while (lines.size() > mLineCount) {  
  244.             try {  
  245.                 m_mbBufBegin += lines.get(0).getBytes(m_strCharsetName).length;  
  246.                 lines.remove(0);  
  247.             } catch (UnsupportedEncodingException e) {  
  248.                 // TODO Auto-generated catch block  
  249.                 e.printStackTrace();  
  250.             }  
  251.         }  
  252.         m_mbBufEnd = m_mbBufBegin;  
  253.         return;  
  254.     }  
  255.   
  256.     protected void prePage() throws IOException {  
  257.         if (m_mbBufBegin <= 0) {  
  258.             m_mbBufBegin = 0;  
  259.             m_isfirstPage = true;  
  260.             return;  
  261.         } else  
  262.             m_isfirstPage = false;  
  263.         m_lines.clear();  
  264.         pageUp();  
  265.         m_lines = pageDown();  
  266.     }  
  267.   
  268.     public void nextPage() throws IOException {  
  269.         if (m_mbBufEnd >= m_mbBufLen) {  
  270.             m_islastPage = true;  
  271.             return;  
  272.         } else  
  273.             m_islastPage = false;  
  274.         m_lines.clear();  
  275.         m_mbBufBegin = m_mbBufEnd;  
  276.         m_lines = pageDown();  
  277.     }  
  278.   
  279.     public void onDraw(Canvas c) {  
  280.         if (m_lines.size() == 0)  
  281.             m_lines = pageDown();  
  282.         if (m_lines.size() > 0) {  
  283.             if (m_book_bg == null)  
  284.                 c.drawColor(m_backColor);  
  285.             else  
  286.                 c.drawBitmap(m_book_bg, 00null);  
  287.             int y = marginHeight;  
  288.             for (String strLine : m_lines) {  
  289.                 y += m_fontSize;  
  290.                 c.drawText(strLine, marginWidth, y, mPaint);  
  291.             }  
  292.         }  
  293.         float fPercent = (float) (m_mbBufBegin * 1.0 / m_mbBufLen);  
  294.         DecimalFormat df = new DecimalFormat("#0.0");  
  295.         String strPercent = df.format(fPercent * 100) + "%";  
  296.         int nPercentWidth = (int) mPaint.measureText("999.9%") + 1;  
  297.         c.drawText(strPercent, mWidth - nPercentWidth, mHeight - 5, mPaint);  
  298.     }  
  299.   
  300.     public void setBgBitmap(Bitmap BG) {  
  301.         if (BG.getWidth() != mWidth || BG.getHeight() != mHeight)  
  302.             m_book_bg = Bitmap.createScaledBitmap(BG, mWidth, mHeight, true);  
  303.         else  
  304.             m_book_bg = BG;  
  305.     }  
  306.   
  307.     public boolean isfirstPage() {  
  308.         return m_isfirstPage;  
  309.     }  
  310.   
  311.     public boolean islastPage() {  
  312.         return m_islastPage;  
  313.     }  
  314. }  


 

  1. package com.book.lee;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.ColorMatrix;  
  7. import android.graphics.ColorMatrixColorFilter;  
  8. import android.graphics.Matrix;  
  9. import android.graphics.Paint;  
  10. import android.graphics.Path;  
  11. import android.graphics.PointF;  
  12. import android.graphics.Region;  
  13. import android.graphics.drawable.GradientDrawable;  
  14. import android.view.MotionEvent;  
  15. import android.view.View;  
  16. import android.widget.Scroller;  
  17.   
  18. public class PageWidget extends View {  
  19.   
  20.     private int mWidth;  
  21.     private int mHeight;  
  22.     private int mCornerX = 0// 拖拽點對應的頁腳  
  23.     private int mCornerY = 0;  
  24.     private Path mPath0;  
  25.     private Path mPath1;  
  26.     Bitmap mCurPageBitmap = null// 當前頁  
  27.     Bitmap mNextPageBitmap = null;  
  28.   
  29.     PointF mTouch = new PointF(); // 拖拽點  
  30.     PointF mBezierStart1 = new PointF(); // 貝塞爾曲線起始點  
  31.     PointF mBezierControl1 = new PointF(); // 貝塞爾曲線控制點  
  32.     PointF mBeziervertex1 = new PointF(); // 貝塞爾曲線頂點  
  33.     PointF mBezierEnd1 = new PointF(); // 貝塞爾曲線結束點  
  34.   
  35.     PointF mBezierStart2 = new PointF(); // 另一條貝塞爾曲線  
  36.     PointF mBezierControl2 = new PointF();  
  37.     PointF mBeziervertex2 = new PointF();  
  38.     PointF mBezierEnd2 = new PointF();  
  39.   
  40.     float mMiddleX;  
  41.     float mMiddleY;  
  42.     float mDegrees;  
  43.     float mTouchToCornerDis;  
  44.     ColorMatrixColorFilter mColorMatrixFilter;  
  45.     Matrix mMatrix;  
  46.     float[] mMatrixArray = { 000000001.0f };  
  47.   
  48.     boolean mIsRTandLB; // 是否屬於右上左下  
  49.     float mMaxLength = (float) Math.hypot(mWidth, mHeight);  
  50.     int[] mBackShadowColors;  
  51.     int[] mFrontShadowColors;  
  52.     GradientDrawable mBackShadowDrawableLR;  
  53.     GradientDrawable mBackShadowDrawableRL;  
  54.     GradientDrawable mFolderShadowDrawableLR;  
  55.     GradientDrawable mFolderShadowDrawableRL;  
  56.   
  57.     GradientDrawable mFrontShadowDrawableHBT;  
  58.     GradientDrawable mFrontShadowDrawableHTB;  
  59.     GradientDrawable mFrontShadowDrawableVLR;  
  60.     GradientDrawable mFrontShadowDrawableVRL;  
  61.   
  62.     Paint mPaint;  
  63.   
  64.     Scroller mScroller;  
  65.   
  66.     public PageWidget(Context context, int w, int h) {  
  67.         super(context);  
  68.         // TODO Auto-generated constructor stub  
  69.         mWidth = w;  
  70.         mHeight = h;  
  71.         mPath0 = new Path();  
  72.         mPath1 = new Path();  
  73.         createDrawable();  
  74.   
  75.         mPaint = new Paint();  
  76.         mPaint.setStyle(Paint.Style.FILL);  
  77.   
  78.         ColorMatrix cm = new ColorMatrix();  
  79.         float array[] = { 0.55f, 00080.0f, 00.55f, 0080.0f, 00,  
  80.                 0.55f, 080.0f, 0000.2f, 0 };  
  81.         cm.set(array);  
  82.         mColorMatrixFilter = new ColorMatrixColorFilter(cm);  
  83.         mMatrix = new Matrix();  
  84.         mScroller = new Scroller(getContext());  
  85.   
  86.         mTouch.x = 0.01f; // 不讓x,y爲0,否則在點計算時會有問題  
  87.         mTouch.y = 0.01f;  
  88.     }  
  89.   
  90.     /** 
  91.      * Author : hmg25 Version: 1.0 Description : 計算拖拽點對應的拖拽腳 
  92.      */  
  93.     public void calcCornerXY(float x, float y) {  
  94.         if (x <= mWidth / 2)  
  95.             mCornerX = 0;  
  96.         else  
  97.             mCornerX = mWidth;  
  98.         if (y <= mHeight / 2)  
  99.             mCornerY = 0;  
  100.         else  
  101.             mCornerY = mHeight;  
  102.         if ((mCornerX == 0 && mCornerY == mHeight)  
  103.                 || (mCornerX == mWidth && mCornerY == 0))  
  104.             mIsRTandLB = true;  
  105.         else  
  106.             mIsRTandLB = false;  
  107.     }  
  108.   
  109.     public boolean doTouchEvent(MotionEvent event) {  
  110.         // TODO Auto-generated method stub  
  111.         if (event.getAction() == MotionEvent.ACTION_MOVE) {  
  112.             mTouch.x = event.getX();  
  113.             mTouch.y = event.getY();  
  114.             this.postInvalidate();  
  115.         }  
  116.         if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  117.             mTouch.x = event.getX();  
  118.             mTouch.y = event.getY();  
  119.             // calcCornerXY(mTouch.x, mTouch.y);  
  120.             // this.postInvalidate();  
  121.         }  
  122.         if (event.getAction() == MotionEvent.ACTION_UP) {  
  123.             if (canDragOver()) {  
  124.                 startAnimation(1200);  
  125.             } else {  
  126.                 mTouch.x = mCornerX - 0.09f;  
  127.                 mTouch.y = mCornerY - 0.09f;  
  128.             }  
  129.   
  130.             this.postInvalidate();  
  131.         }  
  132.         // return super.onTouchEvent(event);  
  133.         return true;  
  134.     }  
  135.   
  136.     /** 
  137.      * Author : hmg25 Version: 1.0 Description : 求解直線P1P2和直線P3P4的交點座標 
  138.      */  
  139.     public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {  
  140.         PointF CrossP = new PointF();  
  141.         // 二元函數通式: y=ax+b  
  142.         float a1 = (P2.y - P1.y) / (P2.x - P1.x);  
  143.         float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x);  
  144.   
  145.         float a2 = (P4.y - P3.y) / (P4.x - P3.x);  
  146.         float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);  
  147.         CrossP.x = (b2 - b1) / (a1 - a2);  
  148.         CrossP.y = a1 * CrossP.x + b1;  
  149.         return CrossP;  
  150.     }  
  151.   
  152.     private void calcPoints() {  
  153.         mMiddleX = (mTouch.x + mCornerX) / 2;  
  154.         mMiddleY = (mTouch.y + mCornerY) / 2;  
  155.         mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)  
  156.                 * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);  
  157.         mBezierControl1.y = mCornerY;  
  158.         mBezierControl2.x = mCornerX;  
  159.         mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)  
  160.                 * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);  
  161.   
  162.         // Log.i("hmg", "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);  
  163.         // Log.i("hmg", "mBezierControl1.x  " + mBezierControl1.x  
  164.         // + "  mBezierControl1.y  " + mBezierControl1.y);  
  165.         // Log.i("hmg", "mBezierControl2.x  " + mBezierControl2.x  
  166.         // + "  mBezierControl2.y  " + mBezierControl2.y);  
  167.   
  168.         mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)  
  169.                 / 2;  
  170.         mBezierStart1.y = mCornerY;  
  171.   
  172.         // 當mBezierStart1.x < 0或者mBezierStart1.x > 480時  
  173.         // 如果繼續翻頁,會出現BUG故在此限制  
  174.         if (mTouch.x > 0 && mTouch.x < mWidth) {  
  175.             if (mBezierStart1.x < 0 || mBezierStart1.x > mWidth) {  
  176.                 if (mBezierStart1.x < 0)  
  177.                     mBezierStart1.x = mWidth - mBezierStart1.x;  
  178.   
  179.                 float f1 = Math.abs(mCornerX - mTouch.x);  
  180.                 float f2 = mWidth * f1 / mBezierStart1.x;  
  181.                 mTouch.x = Math.abs(mCornerX - f2);  
  182.   
  183.                 float f3 = Math.abs(mCornerX - mTouch.x)  
  184.                         * Math.abs(mCornerY - mTouch.y) / f1;  
  185.                 mTouch.y = Math.abs(mCornerY - f3);  
  186.   
  187.                 mMiddleX = (mTouch.x + mCornerX) / 2;  
  188.                 mMiddleY = (mTouch.y + mCornerY) / 2;  
  189.   
  190.                 mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)  
  191.                         * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);  
  192.                 mBezierControl1.y = mCornerY;  
  193.   
  194.                 mBezierControl2.x = mCornerX;  
  195.                 mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)  
  196.                         * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);  
  197.                 // Log.i("hmg", "mTouchX --> " + mTouch.x + "  mTouchY-->  "  
  198.                 // + mTouch.y);  
  199.                 // Log.i("hmg", "mBezierControl1.x--  " + mBezierControl1.x  
  200.                 // + "  mBezierControl1.y -- " + mBezierControl1.y);  
  201.                 // Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x  
  202.                 // + "  mBezierControl2.y -- " + mBezierControl2.y);  
  203.                 mBezierStart1.x = mBezierControl1.x  
  204.                         - (mCornerX - mBezierControl1.x) / 2;  
  205.             }  
  206.         }  
  207.         mBezierStart2.x = mCornerX;  
  208.         mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)  
  209.                 / 2;  
  210.   
  211.         mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),  
  212.                 (mTouch.y - mCornerY));  
  213.   
  214.         mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,  
  215.                 mBezierStart2);  
  216.         mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,  
  217.                 mBezierStart2);  
  218.   
  219.         // Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "  
  220.         // + mBezierEnd1.y);  
  221.         // Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "  
  222.         // + mBezierEnd2.y);  
  223.   
  224.         /* 
  225.          * mBeziervertex1.x 推導 
  226.          * ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化簡等價於 
  227.          * (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4 
  228.          */  
  229.         mBeziervertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;  
  230.         mBeziervertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;  
  231.         mBeziervertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;  
  232.         mBeziervertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;  
  233.     }  
  234.   
  235.     private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {  
  236.         mPath0.reset();  
  237.         mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);  
  238.         mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,  
  239.                 mBezierEnd1.y);  
  240.         mPath0.lineTo(mTouch.x, mTouch.y);  
  241.         mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);  
  242.         mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,  
  243.                 mBezierStart2.y);  
  244.         mPath0.lineTo(mCornerX, mCornerY);  
  245.         mPath0.close();  
  246.   
  247.         canvas.save();  
  248.         canvas.clipPath(path, Region.Op.XOR);  
  249.         canvas.drawBitmap(bitmap, 00null);  
  250.         canvas.restore();  
  251.     }  
  252.   
  253.     private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {  
  254.         mPath1.reset();  
  255.         mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);  
  256.         mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);  
  257.         mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);  
  258.         mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);  
  259.         mPath1.lineTo(mCornerX, mCornerY);  
  260.         mPath1.close();  
  261.   
  262.         mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x  
  263.                 - mCornerX, mBezierControl2.y - mCornerY));  
  264.         int leftx;  
  265.         int rightx;  
  266.         GradientDrawable mBackShadowDrawable;  
  267.         if (mIsRTandLB) {  
  268.             leftx = (int) (mBezierStart1.x);  
  269.             rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);  
  270.             mBackShadowDrawable = mBackShadowDrawableLR;  
  271.         } else {  
  272.             leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);  
  273.             rightx = (int) mBezierStart1.x;  
  274.             mBackShadowDrawable = mBackShadowDrawableRL;  
  275.         }  
  276.         canvas.save();  
  277.         canvas.clipPath(mPath0);  
  278.         canvas.clipPath(mPath1, Region.Op.INTERSECT);  
  279.         canvas.drawBitmap(bitmap, 00null);  
  280.         canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);  
  281.         mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,  
  282.                 (int) (mMaxLength + mBezierStart1.y));  
  283.         mBackShadowDrawable.draw(canvas);  
  284.         canvas.restore();  
  285.     }  
  286.   
  287.     public void setBitmaps(Bitmap bm1, Bitmap bm2) {  
  288.         mCurPageBitmap = bm1;  
  289.         mNextPageBitmap = bm2;  
  290.     }  
  291.   
  292.     public void setScreen(int w, int h) {  
  293.         mWidth = w;  
  294.         mHeight = h;  
  295.     }  
  296.   
  297.     @Override  
  298.     protected void onDraw(Canvas canvas) {  
  299.         canvas.drawColor(0xFFAAAAAA);  
  300.         calcPoints();  
  301.         drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);  
  302.         drawNextPageAreaAndShadow(canvas, mNextPageBitmap);  
  303.         drawCurrentPageShadow(canvas);  
  304.         drawCurrentBackArea(canvas, mCurPageBitmap);  
  305.     }  
  306.   
  307.     /** 
  308.      * Author : hmg25 Version: 1.0 Description : 創建陰影的GradientDrawable 
  309.      */  
  310.     private void createDrawable() {  
  311.         int[] color = { 0x3333330xb0333333 };  
  312.         mFolderShadowDrawableRL = new GradientDrawable(  
  313.                 GradientDrawable.Orientation.RIGHT_LEFT, color);  
  314.         mFolderShadowDrawableRL  
  315.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  316.   
  317.         mFolderShadowDrawableLR = new GradientDrawable(  
  318.                 GradientDrawable.Orientation.LEFT_RIGHT, color);  
  319.         mFolderShadowDrawableLR  
  320.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  321.   
  322.         mBackShadowColors = new int[] { 0xff1111110x111111 };  
  323.         mBackShadowDrawableRL = new GradientDrawable(  
  324.                 GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);  
  325.         mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  326.   
  327.         mBackShadowDrawableLR = new GradientDrawable(  
  328.                 GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);  
  329.         mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  330.   
  331.         mFrontShadowColors = new int[] { 0x801111110x111111 };  
  332.         mFrontShadowDrawableVLR = new GradientDrawable(  
  333.                 GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);  
  334.         mFrontShadowDrawableVLR  
  335.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  336.         mFrontShadowDrawableVRL = new GradientDrawable(  
  337.                 GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);  
  338.         mFrontShadowDrawableVRL  
  339.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  340.   
  341.         mFrontShadowDrawableHTB = new GradientDrawable(  
  342.                 GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);  
  343.         mFrontShadowDrawableHTB  
  344.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  345.   
  346.         mFrontShadowDrawableHBT = new GradientDrawable(  
  347.                 GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);  
  348.         mFrontShadowDrawableHBT  
  349.                 .setGradientType(GradientDrawable.LINEAR_GRADIENT);  
  350.     }  
  351.   
  352.     /** 
  353.      * Author : hmg25 Version: 1.0 Description : 繪製翻起頁的陰影 
  354.      */  
  355.     public void drawCurrentPageShadow(Canvas canvas) {  
  356.         double degree;  
  357.         if (mIsRTandLB) {  
  358.             degree = Math.PI  
  359.                     / 4  
  360.                     - Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x  
  361.                             - mBezierControl1.x);  
  362.         } else {  
  363.             degree = Math.PI  
  364.                     / 4  
  365.                     - Math.atan2(mTouch.y - mBezierControl1.y, mTouch.x  
  366.                             - mBezierControl1.x);  
  367.         }  
  368.         // 翻起頁陰影頂點與touch點的距離  
  369.         double d1 = (float25 * 1.414 * Math.cos(degree);  
  370.         double d2 = (float25 * 1.414 * Math.sin(degree);  
  371.         float x = (float) (mTouch.x + d1);  
  372.         float y;  
  373.         if (mIsRTandLB) {  
  374.             y = (float) (mTouch.y + d2);  
  375.         } else {  
  376.             y = (float) (mTouch.y - d2);  
  377.         }  
  378.         mPath1.reset();  
  379.         mPath1.moveTo(x, y);  
  380.         mPath1.lineTo(mTouch.x, mTouch.y);  
  381.         mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);  
  382.         mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);  
  383.         mPath1.close();  
  384.         float rotateDegrees;  
  385.         canvas.save();  
  386.   
  387.         canvas.clipPath(mPath0, Region.Op.XOR);  
  388.         canvas.clipPath(mPath1, Region.Op.INTERSECT);  
  389.         int leftx;  
  390.         int rightx;  
  391.         GradientDrawable mCurrentPageShadow;  
  392.         if (mIsRTandLB) {  
  393.             leftx = (int) (mBezierControl1.x);  
  394.             rightx = (int) mBezierControl1.x + 25;  
  395.             mCurrentPageShadow = mFrontShadowDrawableVLR;  
  396.         } else {  
  397.             leftx = (int) (mBezierControl1.x - 25);  
  398.             rightx = (int) mBezierControl1.x + 1;  
  399.             mCurrentPageShadow = mFrontShadowDrawableVRL;  
  400.         }  
  401.   
  402.         rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouch.x  
  403.                 - mBezierControl1.x, mBezierControl1.y - mTouch.y));  
  404.         canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);  
  405.         mCurrentPageShadow.setBounds(leftx,  
  406.                 (int) (mBezierControl1.y - mMaxLength), rightx,  
  407.                 (int) (mBezierControl1.y));  
  408.         mCurrentPageShadow.draw(canvas);  
  409.         canvas.restore();  
  410.   
  411.         mPath1.reset();  
  412.         mPath1.moveTo(x, y);  
  413.         mPath1.lineTo(mTouch.x, mTouch.y);  
  414.         mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);  
  415.         mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);  
  416.         mPath1.close();  
  417.         canvas.save();  
  418.         canvas.clipPath(mPath0, Region.Op.XOR);  
  419.         canvas.clipPath(mPath1, Region.Op.INTERSECT);  
  420.         if (mIsRTandLB) {  
  421.             leftx = (int) (mBezierControl2.y);  
  422.             rightx = (int) (mBezierControl2.y + 25);  
  423.             mCurrentPageShadow = mFrontShadowDrawableHTB;  
  424.         } else {  
  425.             leftx = (int) (mBezierControl2.y - 25);  
  426.             rightx = (int) (mBezierControl2.y + 1);  
  427.             mCurrentPageShadow = mFrontShadowDrawableHBT;  
  428.         }  
  429.         rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y  
  430.                 - mTouch.y, mBezierControl2.x - mTouch.x));  
  431.         canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);  
  432.         float temp;  
  433.         if (mBezierControl2.y < 0)  
  434.             temp = mBezierControl2.y - mHeight;  
  435.         else  
  436.             temp = mBezierControl2.y;  
  437.   
  438.         int hmg = (int) Math.hypot(mBezierControl2.x, temp);  
  439.         if (hmg > mMaxLength)  
  440.             mCurrentPageShadow  
  441.                     .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,  
  442.                             (int) (mBezierControl2.x + mMaxLength) - hmg,  
  443.                             rightx);  
  444.         else  
  445.             mCurrentPageShadow.setBounds(  
  446.                     (int) (mBezierControl2.x - mMaxLength), leftx,  
  447.                     (int) (mBezierControl2.x), rightx);  
  448.   
  449.         // Log.i("hmg", "mBezierControl2.x   " + mBezierControl2.x  
  450.         // + "  mBezierControl2.y  " + mBezierControl2.y);  
  451.         mCurrentPageShadow.draw(canvas);  
  452.         canvas.restore();  
  453.     }  
  454.   
  455.     /** 
  456.      * Author : hmg25 Version: 1.0 Description : 繪製翻起頁背面 
  457.      */  
  458.     private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {  
  459.         int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;  
  460.         float f1 = Math.abs(i - mBezierControl1.x);  
  461.         int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;  
  462.         float f2 = Math.abs(i1 - mBezierControl2.y);  
  463.         float f3 = Math.min(f1, f2);  
  464.         mPath1.reset();  
  465.         mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);  
  466.         mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);  
  467.         mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);  
  468.         mPath1.lineTo(mTouch.x, mTouch.y);  
  469.         mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);  
  470.         mPath1.close();  
  471.         GradientDrawable mFolderShadowDrawable;  
  472.         int left;  
  473.         int right;  
  474.         if (mIsRTandLB) {  
  475.             left = (int) (mBezierStart1.x - 1);  
  476.             right = (int) (mBezierStart1.x + f3 + 1);  
  477.             mFolderShadowDrawable = mFolderShadowDrawableLR;  
  478.         } else {  
  479.             left = (int) (mBezierStart1.x - f3 - 1);  
  480.             right = (int) (mBezierStart1.x + 1);  
  481.             mFolderShadowDrawable = mFolderShadowDrawableRL;  
  482.         }  
  483.         canvas.save();  
  484.         canvas.clipPath(mPath0);  
  485.         canvas.clipPath(mPath1, Region.Op.INTERSECT);  
  486.   
  487.         mPaint.setColorFilter(mColorMatrixFilter);  
  488.   
  489.         float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,  
  490.                 mBezierControl2.y - mCornerY);  
  491.         float f8 = (mCornerX - mBezierControl1.x) / dis;  
  492.         float f9 = (mBezierControl2.y - mCornerY) / dis;  
  493.         mMatrixArray[0] = 1 - 2 * f9 * f9;  
  494.         mMatrixArray[1] = 2 * f8 * f9;  
  495.         mMatrixArray[3] = mMatrixArray[1];  
  496.         mMatrixArray[4] = 1 - 2 * f8 * f8;  
  497.         mMatrix.reset();  
  498.         mMatrix.setValues(mMatrixArray);  
  499.         mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);  
  500.         mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);  
  501.         canvas.drawBitmap(bitmap, mMatrix, mPaint);  
  502.         // canvas.drawBitmap(bitmap, mMatrix, null);  
  503.         mPaint.setColorFilter(null);  
  504.         canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);  
  505.         mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,  
  506.                 (int) (mBezierStart1.y + mMaxLength));  
  507.         mFolderShadowDrawable.draw(canvas);  
  508.         canvas.restore();  
  509.     }  
  510.   
  511.     public void computeScroll() {  
  512.         super.computeScroll();  
  513.         if (mScroller.computeScrollOffset()) {  
  514.             float x = mScroller.getCurrX();  
  515.             float y = mScroller.getCurrY();  
  516.             mTouch.x = x;  
  517.             mTouch.y = y;  
  518.             postInvalidate();  
  519.         }  
  520.     }  
  521.   
  522.     private void startAnimation(int delayMillis) {  
  523.         int dx, dy;  
  524.         // dx 水平方向滑動的距離,負值會使滾動向左滾動  
  525.         // dy 垂直方向滑動的距離,負值會使滾動向上滾動  
  526.         if (mCornerX > 0) {  
  527.             dx = -(int) (mWidth + mTouch.x);  
  528.         } else {  
  529.             dx = (int) (mWidth - mTouch.x + mWidth);  
  530.         }  
  531.         if (mCornerY > 0) {  
  532.             dy = (int) (mHeight - mTouch.y);  
  533.         } else {  
  534.             dy = (int) (1 - mTouch.y); // 防止mTouch.y最終變爲0  
  535.         }  
  536.         mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,  
  537.                 delayMillis);  
  538.     }  
  539.   
  540.     public void abortAnimation() {  
  541.         if (!mScroller.isFinished()) {  
  542.             mScroller.abortAnimation();  
  543.         }  
  544.     }  
  545.   
  546.     public boolean canDragOver() {  
  547.         if (mTouchToCornerDis > mWidth / 10)  
  548.             return true;  
  549.         return false;  
  550.     }  
  551.   
  552.     /** 
  553.      * Author : hmg25 Version: 1.0 Description : 是否從左邊翻向右邊 
  554.      */  
  555.     public boolean DragToRight() {  
  556.         if (mCornerX > 0)  
  557.             return false;  
  558.         return true;  
  559.     }  
  560.   
  561. }  


需要工程的朋友還是加QQ羣吧,裏面有一些不錯的開源的工程:50466093

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章