首先申明一點,翻書的效果不是我本人寫的,我只是優化一下加載文件和其它小東東!
先看圖吧!
源碼部分:
- package com.book.lee;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.os.Bundle;
- import android.view.Display;
- 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 BookActivity extends Activity {
- /** Called when the activity is first created. */
- private PageWidget mPageWidget;
- private Bitmap mCurPageBitmap, mNextPageBitmap;
- private Canvas mCurPageCanvas, mNextPageCanvas;
- private 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);
- Display display = getWindowManager().getDefaultDisplay();
- int w = display.getWidth();
- int h = display.getHeight();
- System.out.println(w + "\t" + h);
- mCurPageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- mNextPageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- mCurPageCanvas = new Canvas(mCurPageBitmap);
- mNextPageCanvas = new Canvas(mNextPageBitmap);
- pagefactory = new BookPageFactory(w, h);
- pagefactory.setBgBitmap(BitmapFactory.decodeResource(getResources(),
- R.drawable.bg));
- if (!copyFile()) {
- Toast.makeText(this, "電子書不存在!", Toast.LENGTH_SHORT).show();
- } else {
- pagefactory.openbook("/sdcard/test.txt");
- pagefactory.onDraw(mCurPageCanvas);
- }
- mPageWidget = new PageWidget(this, w, h);
- setContentView(mPageWidget);
- 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;
- }
- });
- }
- protected boolean copyFile() {
- try {
- String dst = "/sdcard/test.txt";
- File outFile = new File(dst);
- if (!outFile.exists()) {
- InputStream inStream = getResources().openRawResource(
- R.raw.test);
- outFile.createNewFile();
- FileOutputStream fs = new FileOutputStream(outFile);
- byte[] buffer = new byte[1024 * 1024];// 1MB
- int byteread = 0;
- while ((byteread = inStream.read(buffer)) != -1) {
- fs.write(buffer, 0, byteread);
- }
- inStream.close();
- fs.close();
- }
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
- }
- /**
- * Author : hmg25
- * Description :
- */
- package com.book.lee;
- 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.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) {
- try {
- 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);
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- 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) {
- 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 boolean islastPage() {
- return m_islastPage;
- }
- }
- package com.book.lee;
- 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 int mWidth;
- private int mHeight;
- 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;
- }
- }
需要工程的朋友還是加QQ羣吧,裏面有一些不錯的開源的工程:50466093