|
package com.newBook;
/*
* Copyright (c) 2010
*
* Author: Wallace Wang
* Email: wallage@qq.com
*/
import java.util.Date;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.PorterDuff.Mode;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class eBook extends FrameLayout{
public static final String LOG_TAG = "eBook";
int totalPageNum;
Context mContext;
boolean hasInit = false;
final int defaultWidth = 600 , defaultHeight = 400;
int contentWidth = 0;
int contentHeight = 0;
View leftPage,rightPage,llPage,lrPage,rrPage,rlPage;
LinearLayout invisibleView;
LinearLayout mView;
MidView mMidView;
bookView mBookView;
Handler AniEndHandle;
static boolean closeBook = false;
private enum Corner {
LeftTop,
RightTop,
LeftBottom,
RightBottom,
None
};
private Corner mSelectCorner;
final int clickCornerLen = 250*250; //50dip
float scrollX = 0,scrollY = 0;
int indexPage = 0;
public enum BookState {
ABOUT_TO_ANIMATE,
ANIMATING,
ANIMATE_END,
READY,
TRACKING
};
private BookState mState;
private Point aniStartPos;
private Point aniStopPos;
private Date aniStartTime;
private long aniTime = 800;
private long timeOffset = 10;
Listener mListener;
PageAdapter mPageAdapter;
private GestureDetector mGestureDetector;
private BookOnGestureListener mGestureListener;
public eBook(Context context) {
super(context);
Init(context);
}
public eBook(Context context, AttributeSet attrs) {
super(context, attrs);
Init(context);
}
public eBook(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Init(context);
}
public static interface Listener {
public void onPrevPage();
public void onNextPage();
public void onInit();
}
public static interface PageAdapter{
public View getView(int position);
public int getCount();
}
public void setListener(Listener listener) {
Log.d(LOG_TAG,"setListener");
mListener = listener;
}
public void setPageAdapter(PageAdapter pa){
Log.d(LOG_TAG,"setPageAdapter");
mPageAdapter = pa;
}
public void Init(Context context){
totalPageNum = 0;
mContext = context;
mSelectCorner = Corner.None;
mGestureListener = new BookOnGestureListener();
mGestureDetector = new GestureDetector(mGestureListener);
mGestureDetector.setIsLongpressEnabled(false);
AniEndHandle = new Handler();
this.setOnTouchListener(touchListener);
this.setLongClickable(true);
}
public View getLeftPage(){
return leftPage;
}
public View getRightPage(){
return rightPage;
}
public View getPrevPage1(){
return lrPage;
}
public View getPrevPage2(){
return llPage;
}
public View getNextPage1(){
return rlPage;
}
public View getNextPage2(){
return rrPage;
}
public int getIndexForLeftPage(){
return indexPage;
}
public int getIndexForRightPage(){
return indexPage + 1;
}
public void setIndexForLeftPage(int index){
if(index >= 0 && index < totalPageNum){
if((index % 2) == 0)
indexPage = index;
else
indexPage = index - 1;
}
}
public void updatePageView(){
Log.d(LOG_TAG,"updatePageView");
if(indexPage < 0 || indexPage > totalPageNum - 1){
Log.d(LOG_TAG,"indexPage exceed bound");
return;
}
invisibleView.removeAllViews();
mView.removeAllViews();
leftPage = mPageAdapter.getView(indexPage);
if(leftPage == null)leftPage = new WhiteView(mContext);
leftPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
mView.addView(leftPage);
lrPage = mPageAdapter.getView(indexPage-1);
if(lrPage == null)lrPage = new WhiteView(mContext);
lrPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
invisibleView.addView(lrPage);
llPage = mPageAdapter.getView(indexPage-2);
if(llPage == null)llPage = new WhiteView(mContext);
llPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
invisibleView.addView(llPage);
rightPage = mPageAdapter.getView(indexPage+1);
if(rightPage == null)rightPage = new WhiteView(mContext);
rightPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
mView.addView(rightPage);
rlPage = mPageAdapter.getView(indexPage+2);
if(rlPage == null)rlPage = new WhiteView(mContext);
rlPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
invisibleView.addView(rlPage);
rrPage = mPageAdapter.getView(indexPage+3);
if(rrPage == null)rrPage = new WhiteView(mContext);
rrPage.setLayoutParams(new LayoutParams(contentWidth/2,contentHeight));
invisibleView.addView(rrPage);
Log.d(LOG_TAG,"updatePageView finish");
}
OnTouchListener touchListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.d(LOG_TAG, "onTouch " + " x: " + event.getX() + " y: " + event.getY() +
" mState:" + mState);
mGestureDetector.onTouchEvent(event);
int action = event.getAction();
if (action == MotionEvent.ACTION_UP && mSelectCorner != Corner.None
&& mState == BookState.TRACKING) {
if(mState == BookState.ANIMATING)return false;
if(mSelectCorner == Corner.LeftTop || mSelectCorner == Corner.RightTop){
if(scrollX < contentWidth/2){
aniStopPos = new Point(0,0);
}else{
aniStopPos = new Point(contentWidth,0);
}
}else if(mSelectCorner == Corner.LeftBottom || mSelectCorner == Corner.RightBottom){
if(scrollX < contentWidth/2){
aniStopPos = new Point(0,contentHeight);
}else{
aniStopPos = new Point(contentWidth,contentHeight);
}
}
aniStartPos = new Point((int)scrollX,(int)scrollY);
aniTime = 800;
mState = BookState.ABOUT_TO_ANIMATE;
closeBook = true;
aniStartTime = new Date();
mBookView.startAnimation();
}
return false;
}
};
class BookOnGestureListener implements OnGestureListener {
public boolean onDown(MotionEvent event) {
Log.d(LOG_TAG, "onDown");
if(mState == BookState.ANIMATING)return false;
float x = event.getX(), y = event.getY();
int w = contentWidth, h = contentHeight;
if(x*x + y*y < clickCornerLen){
if(indexPage > 1){
mSelectCorner = Corner.LeftTop;
aniStartPos = new Point(0,0);
}
}else if((x-w)*(x-w)+ y*y < clickCornerLen){
if(indexPage < totalPageNum-2){
mSelectCorner = Corner.RightTop;
aniStartPos = new Point(contentWidth,0);
}
}else if(x*x + (y-h)*(y-h) < clickCornerLen){
if(indexPage > 1){
mSelectCorner = Corner.LeftBottom;
aniStartPos = new Point(0,contentHeight);
}
}else if((x-w)*(x-w) + (y-h)*(y-h) < clickCornerLen){
if(indexPage < totalPageNum-2){
mSelectCorner = Corner.RightBottom;
aniStartPos = new Point(contentWidth,contentHeight);
}
}
if(mSelectCorner != Corner.None){
aniStopPos = new Point((int)x,(int)y);
aniTime = 800;
mState = BookState.ABOUT_TO_ANIMATE;
closeBook = false;
aniStartTime = new Date();
mBookView.startAnimation();
}
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d(LOG_TAG, "onFling velocityX:"+velocityX+" velocityY:"+velocityY);
if(mSelectCorner != Corner.None){
if(mSelectCorner == Corner.LeftTop || mSelectCorner == Corner.RightTop){
if(velocityX < 0){
aniStopPos = new Point(0,0);
}else{
aniStopPos = new Point(contentWidth,0);
}
}else if(mSelectCorner == Corner.LeftBottom || mSelectCorner == Corner.RightBottom){
if(velocityX < 0){
aniStopPos = new Point(0,contentHeight);
}else{
aniStopPos = new Point(contentWidth,contentHeight);
}
}
Log.d(LOG_TAG, "onFling animate");
aniStartPos = new Point((int)scrollX,(int)scrollY);
aniTime = 1000;
mState = BookState.ABOUT_TO_ANIMATE;
closeBook = true;
aniStartTime = new Date();
mBookView.startAnimation();
}
return false;
}
public void onLongPress(MotionEvent e) {
Log.d(LOG_TAG, "onLongPress");
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// if(mState == BookState.ANIMATING)return false;
mState = BookState.TRACKING;
if(mSelectCorner != Corner.None){
scrollX = e2.getX();
scrollY = e2.getY();
mBookView.startAnimation();
}
return false;
}
public void onShowPress(MotionEvent e) {
Log.d(LOG_TAG, "onShowPress");
}
public boolean onSingleTapUp(MotionEvent e) {
Log.d(LOG_TAG, "onSingleTapUp");
if(mSelectCorner != Corner.None){
if(mSelectCorner == Corner.LeftTop || mSelectCorner == Corner.RightTop){
if(scrollX < contentWidth/2){
aniStopPos = new Point(0,0);
}else{
aniStopPos = new Point(contentWidth,0);
}
}else if(mSelectCorner == Corner.LeftBottom || mSelectCorner == Corner.RightBottom){
if(scrollX < contentWidth/2){
aniStopPos = new Point(0,contentHeight);
}else{
aniStopPos = new Point(contentWidth,contentHeight);
}
}
aniStartPos = new Point((int)scrollX,(int)scrollY);
aniTime = 800;
mState = BookState.ABOUT_TO_ANIMATE;
closeBook = true;
aniStartTime = new Date();
mBookView.startAnimation();
}
return false;
}
}
protected void onFinishInflate() {
Log.d(LOG_TAG, "onFinishInflate");
super.onFinishInflate();
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
contentWidth = this.getWidth();
contentHeight = this.getHeight();
if(contentWidth == 0) contentWidth = defaultWidth;
if(contentHeight == 0) contentHeight = defaultHeight;
Log.d(LOG_TAG, "onLayout, width:" + contentWidth + " height:" + contentHeight);
}
protected void dispatchDraw(Canvas canvas) {
Log.d(LOG_TAG, "dispatchDraw");
super.dispatchDraw(canvas);
if(!hasInit){
hasInit = true;
indexPage = 0;
if(mPageAdapter == null){
throw new RuntimeException("please set the PageAdapter on init");
}
totalPageNum = mPageAdapter.getCount();
mView = new LinearLayout(mContext);
mView.setLayoutParams(new LayoutParams(contentWidth,contentHeight));
mView.setBackgroundColor(0xffffffff);
mState = BookState.READY;
invisibleView = new LinearLayout(mContext);
invisibleView.setLayoutParams(new LayoutParams(contentWidth,contentHeight));
mMidView = new MidView(mContext);
mMidView.setLayoutParams(new LayoutParams(contentWidth,contentHeight));
this.addView(invisibleView);
this.addView(mView);
this.addView(mMidView);
mBookView = new bookView(mContext);
mBookView.setLayoutParams(new LayoutParams(contentWidth,contentHeight));
this.addView(mBookView);
// invisibleView.setVisibility(INVISIBLE);
// mBookView.setVisibility(GONE);
updatePageView();
invalidate();
if(mListener != null)mListener.onInit();
}else if (mState == BookState.READY){
mBookView.update();
}
}
class bookView extends SurfaceView implements SurfaceHolder.Callback{
DrawThread dt; //后台屏幕绘制线程
SurfaceHolder surfaceHolder;
Paint mDarkPaint = new Paint();
Paint mPaint = new Paint();
Bitmap tmpBmp = Bitmap.createBitmap(contentWidth/2,contentHeight,Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(tmpBmp);
Paint bmpPaint = new Paint();
Paint ivisiblePaint = new Paint();
public bookView(Context context) {
super(context);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
mDarkPaint.setColor(0x88000000);
Shader mLinearGradient = new LinearGradient(0, 0, contentWidth, 0,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.MIRROR);
mPaint.setAntiAlias(true);
mPaint.setShader(mLinearGradient);
bmpPaint.setFilterBitmap(true);
bmpPaint.setAntiAlias(true);
ivisiblePaint.setAlpha(0);
ivisiblePaint.setFilterBitmap(true);
ivisiblePaint.setAntiAlias(true);
ivisiblePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
}
public void startAnimation(){
// update();
if(dt == null){
Log.d(LOG_TAG,"startAnimation");
// mBookView.setVisibility(VISIBLE);
dt = new DrawThread(this,getHolder());
dt.start();
}
}
public void stopAnimation(){
Log.d(LOG_TAG,"stopAnimation");
// AniEndHandle.post(new Runnable(){
// public void run() {
// mBookView.setVisibility(GONE);
// }
// });
if(dt != null){
dt.flag = false;
Thread t = dt;
dt = null;
t.interrupt();
}
}
public void drawLT(Canvas canvas){
double dx = scrollX - contentWidth/2, dy = scrollY;
double len = Math.sqrt(dx*dx + dy*dy);
if(len > contentWidth/2){
scrollX = (float) (contentWidth*dx/(2.0*len)) + contentWidth/2;
scrollY = (float) (contentWidth*dy/(2.0*len));
}
dy = contentHeight - scrollY;
len = Math.sqrt(dx*dx + dy*dy);
double d = Math.sqrt(contentWidth*contentWidth/4 + contentHeight*contentHeight);
if(len > d){
scrollX = (float) (d*dx/len) + contentWidth/2;
scrollY = contentHeight - (float) (d*dy/len);
}
double px = scrollX;
double py = scrollY;
double arc = 2 * Math.atan(py/px)*180/Math.PI;
Matrix m = new Matrix();
m.postTranslate(scrollX - contentWidth/2, scrollY);
m.postRotate((float)(arc),scrollX,scrollY);
lrPage.draw(mCanvas);
Paint ps = new Paint();
Shader lg1 = new LinearGradient(contentWidth/2, 0,
contentWidth/2 - (float)px,(float)py,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg1);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
canvas.drawBitmap(tmpBmp, m, bmpPaint);
llPage.draw(mCanvas);
Shader lg2 = new LinearGradient(scrollX,scrollY,0, 0,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg2);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
arc = arc*Math.PI/360;
Path path = new Path();
double r = Math.sqrt(px * px + py * py);
double p1 = r/(2*Math.cos(arc));
double p2 = r/(2*Math.sin(arc));
Log.d(LOG_TAG,"p1: " + p1 + " p2:" + p2);
if(arc == 0){
path.moveTo((float)p1, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo((float)p1, contentHeight);
path.close();
}else if(p2 > contentHeight || p2 < 0){
double p3 = (p2 - contentHeight)*Math.tan(arc);
path.moveTo((float)p1, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo((float)p3, contentHeight);
path.close();
}else{
path.moveTo((float)p1, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo(0, contentHeight);
path.lineTo(0, (float)p2);
path.close();
}
mCanvas.drawPath(path, ivisiblePaint);
canvas.drawBitmap(tmpBmp, 0, 0, null);
}
public void drawLB(Canvas canvas){
double dx = scrollX - contentWidth/2, dy = scrollY - contentHeight;
double len = Math.sqrt(dx*dx + dy*dy);
if(len > contentWidth/2){
scrollX = (float) (contentWidth*dx/(2.0*len)) + contentWidth/2;
scrollY = (float) (contentWidth*dy/(2.0*len)) + contentHeight;
}
dy = scrollY;
len = Math.sqrt(dx*dx + dy*dy);
double d = Math.sqrt(contentWidth*contentWidth/4 + contentHeight*contentHeight);
if(len > d){
scrollX = (float) (d*dx/len) + contentWidth/2;
scrollY = (float) (d*dy/len);
}
double px = scrollX;
double py = contentHeight - scrollY;
double arc = 2 * Math.atan(py/px)*180/Math.PI;
Matrix m = new Matrix();
m.postTranslate(scrollX - contentWidth/2, scrollY - contentHeight);
m.postRotate((float)(-arc),scrollX,scrollY);
lrPage.draw(mCanvas);
Paint ps = new Paint();
Shader lg1 = new LinearGradient(contentWidth/2, contentHeight,
contentWidth/2 - (float)px, contentHeight - (float)py,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg1);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
canvas.drawBitmap(tmpBmp, m, bmpPaint);
llPage.draw(mCanvas);
Shader lg2 = new LinearGradient(scrollX,scrollY,0, contentHeight,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg2);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
arc = arc*Math.PI/360;
Path path = new Path();
double r = Math.sqrt(px * px + py * py);
double p1 = r/(2*Math.cos(arc));
double p2 = r/(2*Math.sin(arc));
Log.d(LOG_TAG,"p1: " + p1 + " p2:" + p2);
if(arc == 0){
path.moveTo((float)p1, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo((float)p1, contentHeight);
path.close();
}else if(p2 > contentHeight || p2 < 0){
double p3 = (p2 - contentHeight)*Math.tan(arc);
path.moveTo((float)p3, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo((float)p1, contentHeight);
path.close();
}else{
path.moveTo(0, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo((float)p1, contentHeight);
path.lineTo(0, contentHeight - (float)p2);
path.close();
}
mCanvas.drawPath(path, ivisiblePaint);
canvas.drawBitmap(tmpBmp, 0, 0, null);
}
public void drawRT(Canvas canvas){
double dx = scrollX - contentWidth/2, dy = scrollY;
double len = Math.sqrt(dx*dx + dy*dy);
if(len > contentWidth/2){
scrollX = (float) (contentWidth*dx/(2.0*len)) + contentWidth/2;
scrollY = (float) (contentWidth*dy/(2.0*len));
}
dy = contentHeight - scrollY;
len = Math.sqrt(dx*dx + dy*dy);
double d = Math.sqrt(contentWidth*contentWidth/4 + contentHeight*contentHeight);
if(len > d){
scrollX = (float) (d*dx/len) + contentWidth/2;
scrollY = contentHeight - (float) (d*dy/len);
}
double px = contentWidth - scrollX;
double py = scrollY;
double arc = 2 * Math.atan(py/px)*180/Math.PI;
Matrix m = new Matrix();
m.postTranslate(scrollX, scrollY);
m.postRotate((float)(-arc),scrollX,scrollY);
rlPage.draw(mCanvas);
Paint ps = new Paint();
Shader lg1 = new LinearGradient(0, 0, (float)px, (float)py,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg1);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
canvas.drawBitmap(tmpBmp, m, bmpPaint);
rrPage.draw(mCanvas);
Shader lg2 = new LinearGradient(scrollX-contentWidth/2, scrollY,
contentWidth/2, 0,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg2);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
arc = arc*Math.PI/360;
Path path = new Path();
double r = Math.sqrt(px * px + py * py);
double p1 = contentWidth/2 - r/(2*Math.cos(arc));
double p2 = r/(2*Math.sin(arc));
Log.d(LOG_TAG,"p1: " + p1 + " p2:" + p2);
if(arc == 0){
path.moveTo(0, 0);
path.lineTo((float)p1, 0);
path.lineTo((float)p1, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}else if(p2 > contentHeight || p2 < 0){
double p3 = contentWidth/2 - (p2 - contentHeight)*Math.tan(arc);
path.moveTo(0, 0);
path.lineTo((float)p1, 0);
path.lineTo((float)p3, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}else{
path.moveTo(0, 0);
path.lineTo((float)p1, 0);
path.lineTo(contentWidth/2, (float)p2);
path.lineTo(contentWidth/2, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}
mCanvas.drawPath(path, ivisiblePaint);
canvas.drawBitmap(tmpBmp, contentWidth/2, 0, null);
}
public void drawRB(Canvas canvas){
double dx = scrollX - contentWidth/2, dy = contentHeight - scrollY;
double len = Math.sqrt(dx*dx + dy*dy);
if(len > contentWidth/2){
scrollX = (float) (contentWidth*dx/(2.0*len)) + contentWidth/2;
scrollY = contentHeight - (float) (contentWidth*dy/(2.0*len));
}
dy = scrollY;
len = Math.sqrt(dx*dx + dy*dy);
double d = Math.sqrt(contentWidth*contentWidth/4 + contentHeight*contentHeight);
if(len > d){
scrollX = (float) (d*dx/len) + contentWidth/2;
scrollY = (float) (d*dy/len);
}
double px = contentWidth - scrollX;
double py = contentHeight - scrollY;
double arc = 2 * Math.atan(py/px)*180/Math.PI;
Matrix m = new Matrix();
m.postTranslate(scrollX, scrollY - contentHeight);
m.postRotate((float)(arc),scrollX,scrollY);
rlPage.draw(mCanvas);
Paint ps = new Paint();
Shader lg1 = new LinearGradient(0, contentHeight,
(float)px,contentHeight-(float)py,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg1);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
canvas.drawBitmap(tmpBmp, m, bmpPaint);
rrPage.draw(mCanvas);
Shader lg2 = new LinearGradient(scrollX-contentWidth/2, scrollY,
contentWidth/2, contentHeight,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.CLAMP);
ps.setShader(lg2);
mCanvas.drawRect(0, 0, contentWidth/2, contentHeight, ps);
arc = arc*Math.PI/360;
Path path = new Path();
double r = Math.sqrt(px * px + py * py);
double p1 = contentWidth/2 - r/(2*Math.cos(arc));
double p2 = r/(2*Math.sin(arc));
Log.d(LOG_TAG,"p1: " + p1 + " p2:" + p2);
if(arc == 0){
path.moveTo(0, 0);
path.lineTo((float)p1, 0);
path.lineTo((float)p1, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}else if(p2 > contentHeight || p2 < 0){
double p3 = contentWidth/2 - (p2 - contentHeight)*Math.tan(arc);
path.moveTo(0, 0);
path.lineTo((float)p3, 0);
path.lineTo((float)p1, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}else{
path.moveTo(0, 0);
path.lineTo(contentWidth/2, 0);
path.lineTo(contentWidth/2, contentHeight - (float)p2);
path.lineTo((float)p1, contentHeight);
path.lineTo(0, contentHeight);
path.close();
}
mCanvas.drawPath(path, ivisiblePaint);
canvas.drawBitmap(tmpBmp, contentWidth/2, 0, null);
}
public void drawPrevPageEnd(Canvas canvas){
llPage.draw(mCanvas);
canvas.drawBitmap(tmpBmp, 0, 0, null);
lrPage.draw(mCanvas);
canvas.drawBitmap(tmpBmp, contentWidth/2, 0, null);
canvas.drawRect(0, 0, contentWidth, contentHeight, mPaint);
canvas.drawLine(contentWidth/2, 0, contentWidth/2, contentHeight, mDarkPaint);
}
public void drawNextPageEnd(Canvas canvas) {
rlPage.draw(mCanvas);
canvas.drawBitmap(tmpBmp, 0, 0, null);
rrPage.draw(mCanvas);
canvas.drawBitmap(tmpBmp, contentWidth / 2, 0, null);
canvas.drawRect(0, 0, contentWidth, contentHeight, mPaint);
canvas.drawLine(contentWidth/2, 0, contentWidth/2, contentHeight, mDarkPaint);
}
public void drawPage(Canvas canvas){
if(mSelectCorner == Corner.LeftTop){
Log.d(LOG_TAG,"click left top");
drawLT(canvas);
}else if(mSelectCorner == Corner.LeftBottom){
Log.d(LOG_TAG,"click left bottom");
drawLB(canvas);
}else if(mSelectCorner == Corner.RightTop){
Log.d(LOG_TAG,"click right top");
drawRT(canvas);
}else if(mSelectCorner == Corner.RightBottom){
Log.d(LOG_TAG,"click right bottom");
drawRB(canvas);
}
}
public void update(){
Canvas canvas = surfaceHolder.lockCanvas(null);//获取BallView的画布
try{
synchronized(surfaceHolder){
doDraw(canvas); //调用BallView的doDraw方法进行绘制
}
}
catch(Exception e){
e.printStackTrace(); //捕获并打印异常
}
finally{
if(canvas != null){ //如果canvas不为空
surfaceHolder.unlockCanvasAndPost(canvas);//surfaceHolder解锁并将画布对象传回
}
}
}
protected void doDraw(Canvas canvas) {
Log.d(LOG_TAG, "bookView doDraw");
// super.onDraw(canvas);
mView.draw(canvas);
canvas.drawRect(0, 0, contentWidth, contentHeight, mPaint);
canvas.drawLine(contentWidth/2, 0, contentWidth/2, contentHeight, mDarkPaint);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
update();
}
public void surfaceDestroyed(SurfaceHolder holder) {
if(dt != null){
dt.flag = false; //停止线程的执行
dt = null; //将dt指向的对象声明为垃圾
}
}
}
public boolean getAnimateData(){
long time = aniTime;
Date date = new Date();
long t = date.getTime()-aniStartTime.getTime();
t += timeOffset;
if(t < 0 || t > time){
mState = BookState.ANIMATE_END;
return false;
}else{
mState = BookState.ANIMATING;
double sx = aniStopPos.x - aniStartPos.x;
double gx = 2*sx/(time*time);
scrollX = (float) (gx*time*t - gx*t*t/2 + aniStartPos.x);
double sy = aniStopPos.y - aniStartPos.y;
double gy = 2*sy/(time*time);
scrollY = (float) (gy*time*t - gy*t*t/2 + aniStartPos.y);
return true;
}
}
public void handleAniEnd(Canvas canvas){
if(closeBook){
closeBook = false;
if(mSelectCorner == Corner.LeftTop || mSelectCorner == Corner.LeftBottom){
if(scrollX > contentWidth/2){
Log.d(LOG_TAG,"handleAniEnd -2,indexPage:"+ (indexPage-2));
indexPage -= 2;
mBookView.drawPrevPageEnd(canvas);
AniEndHandle.post(new Runnable(){
public void run() {
updatePageView();
if(mListener != null){
Log.d(LOG_TAG,"onPrevPage");
mListener.onPrevPage();
}
}
});
}else{
mBookView.doDraw(canvas);
}
}else if(mSelectCorner == Corner.RightTop || mSelectCorner == Corner.RightBottom){
if(scrollX < contentWidth/2){
Log.d(LOG_TAG,"handleAniEnd +2,indexPage:"+ (indexPage+2));
indexPage += 2;
mBookView.drawNextPageEnd(canvas);
AniEndHandle.post(new Runnable(){
public void run() {
updatePageView();
if(mListener != null){
Log.d(LOG_TAG,"onNextPage");
mListener.onNextPage();
}
}
});
}else{
mBookView.doDraw(canvas);
}
}
mSelectCorner = Corner.None;
mState = BookState.READY;
}else{
mState = BookState.TRACKING;
}
mBookView.stopAnimation();
AniEndHandle.post(new Runnable(){
public void run() {
eBook.this.invalidate();
}
});
}
class WhiteView extends View{
public WhiteView(Context context) {
super(context);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
}
}
class MidView extends View{
public MidView(Context context) {
super(context);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint mPaint = new Paint();
Shader mLinearGradient = new LinearGradient(0, 0, contentWidth, 0,
new int[] { 0x00000000, 0x33000000,0x00000000 },
new float[] { 0.35f, 0.5f, 0.65f },
Shader.TileMode.MIRROR);
mPaint.setAntiAlias(true);
mPaint.setShader(mLinearGradient);
canvas.drawRect(0, 0, contentWidth, contentHeight, mPaint);
Paint mDarkPaint = new Paint();
mDarkPaint.setColor(0x88000000);
canvas.drawLine(contentWidth/2, 0, contentWidth/2, contentHeight, mDarkPaint);
}
}
public class DrawThread extends Thread{
bookView bv; //bookView对象引用
SurfaceHolder surfaceHolder;//SurfaceHolder对象引用
boolean flag=false; //线程执行标志位
int sleepSpan = 30; //休眠时间
public DrawThread(bookView bv,SurfaceHolder surfaceHolder){
this.bv = bv; //为BallView对象应用赋值
this.surfaceHolder = surfaceHolder; //为SurfaceHolder对象应用赋值
this.flag = true; //设置标志位
}
public void run(){
Canvas canvas = null;//声明一个Canvas对象
while(flag){
try{
canvas = surfaceHolder.lockCanvas(null);//获取BallView的画布
if(canvas == null)continue;
synchronized(surfaceHolder){
if(mState == BookState.ABOUT_TO_ANIMATE || mState == BookState.ANIMATING){
bv.doDraw(canvas); //调用BallView的doDraw方法进行绘制
getAnimateData();
bv.drawPage(canvas);
}else if(mState == BookState.TRACKING){
bv.doDraw(canvas);
bv.drawPage(canvas);
}else if(mState == BookState.ANIMATE_END){
handleAniEnd(canvas);
}
}
}
catch(Exception e){
e.printStackTrace(); //捕获并打印异常
}
finally{
if(canvas != null){ //如果canvas不为空
surfaceHolder.unlockCanvasAndPost(canvas);//surfaceHolder解锁并将画布对象传回
}
}
try{
Thread.sleep(sleepSpan); //线程休眠一段时间
}
catch(Exception e){
e.printStackTrace(); //捕获并打印异常
}
}
}
}
} |
|