pda/zhuike/.svn/pristine/da/da620167d849e794060d2c491d8...

917 lines
32 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.novelbook.android.view;
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.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.PageFactory;
public class BookPageWidget extends View {
private final static String TAG = "BookPageWidget";
private int mScreenWidth = 0; // 屏幕宽
private int mScreenHeight = 0; // 屏幕高
private Context mContext;
private int mCornerX = 1; // 拖拽点对应的页脚
private int mCornerY = 1;
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; // 是否属于右上左下
private float mMaxLength ;
int[] mBackShadowColors;// 背面颜色组
int[] mFrontShadowColors;// 前面颜色组
GradientDrawable mBackShadowDrawableLR; // 有阴影的GradientDrawable
GradientDrawable mBackShadowDrawableRL;
GradientDrawable mFolderShadowDrawableLR;
GradientDrawable mFolderShadowDrawableRL;
GradientDrawable mFrontShadowDrawableHBT;
GradientDrawable mFrontShadowDrawableHTB;
GradientDrawable mFrontShadowDrawableVLR;
GradientDrawable mFrontShadowDrawableVRL;
Paint mPaint;
Scroller mScroller;
private int mBgColor = 0xFFCEC29C;
private float actiondownX,actiondownY;
private TouchListener mTouchListener;
public BookPageWidget(Context context) {
this(context,null);
}
public BookPageWidget(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public BookPageWidget(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initPage();
mPath0 = new Path();
mPath1 = new Path();
mMaxLength = (float) Math.hypot(mScreenWidth, mScreenHeight);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
// mPaint.setAlpha(150);
createDrawable();
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 };
float array[] = { 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0,1, 0, 0,
0, 0, 0, 1, 0 };
cm.set(array);
mColorMatrixFilter = new ColorMatrixColorFilter(cm);
mMatrix = new Matrix();
mScroller = new Scroller(getContext(),new LinearInterpolator());
mTouch.x = 0.01f; // 不让x,y为0,否则在点计算时会有问题
mTouch.y = 0.01f;
}
private void initPage(){
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metric = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metric);
mScreenWidth = metric.widthPixels;
// mScreenHeight = metric.heightPixels;
// mScreenHeight = CommonUtil.getDpi(mContext);
mScreenHeight = CommonUtil.getScreenHeight(mContext);
mCurPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565); //android:LargeHeap=true use in manifest application
mNextPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565);
}
public Bitmap getCurPage(){
return mCurPageBitmap;
}
public Bitmap getNextPage(){
return mNextPageBitmap;
}
public void changePage(){
Bitmap bitmap = mCurPageBitmap;
mCurPageBitmap = mNextPageBitmap;
mNextPageBitmap = bitmap;
postInvalidate();
}
public void setBgColor(int color){
mBgColor = color;
}
/**
* 创建阴影的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);
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFAAAAAA);
canvas.drawColor(mBgColor);
Log.e("onDraw","isNext:" + isNext + " isRuning:" + isRuning);
if (isRuning) {
if (isNext) {
calcPoints();
drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);
drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
drawCurrentPageShadow(canvas);
drawCurrentBackArea(canvas, mCurPageBitmap);
}else{
calcPoints();
drawCurrentPageArea(canvas, mNextPageBitmap, mPath0);
drawNextPageAreaAndShadow(canvas, mCurPageBitmap);
drawCurrentPageShadow(canvas);
drawCurrentBackArea(canvas, mNextPageBitmap);
}
} else {
if (cancelPage){
canvas.drawBitmap(mCurPageBitmap, 0, 0, null);
}else {
canvas.drawBitmap(mNextPageBitmap, 0, 0, null);
}
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
float x = mScroller.getCurrX();
float y = mScroller.getCurrY();
mTouch.x = x;
mTouch.y = y;
if (mScroller.getFinalX() == x && mScroller.getFinalY() == y){
isRuning = false;
}
postInvalidate();
}
super.computeScroll();
}
//是否移动了
private Boolean isMove = false;
//是否翻到下一页
private Boolean isNext = false;
//是否取消翻页
private Boolean cancelPage = false;
//是否没下一页或者上一页
private Boolean noNext = false;
private int downX = 0;
private int downY = 0;
private int moveX = 0;
private int moveY = 0;
//翻页动画是否在执行
private Boolean isRuning =false;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (PageFactory.getStatus() == PageFactory.Status.OPENING){
return true;
}
int x = (int)event.getX();
int y = (int)event.getY();
mTouch.x = event.getX();
mTouch.y = event.getY();
//触摸y中间位置吧y变成屏幕高度
if ((downY > mScreenHeight / 3 && downY < mScreenHeight * 2 / 3) || (isMove && !isNext)){
mTouch.y = mScreenHeight;
}
if (downY > mScreenHeight / 3 && downY < mScreenHeight / 2 && isNext){
mTouch.y = 1;
}
if (event.getAction() == MotionEvent.ACTION_DOWN){
downX = (int) event.getX();
downY = (int) event.getY();
moveX = 0;
moveY = 0;
isMove = false;
// cancelPage = false;
noNext = false;
isNext = false;
isRuning = false;
calcCornerXY(downX,downY);
abortAnimation();
Log.e(TAG,"ACTION_DOWN");
}else if (event.getAction() == MotionEvent.ACTION_MOVE){
final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
//判断是否移动了
if (!isMove) {
isMove = Math.abs(downX - x) > slop || Math.abs(downY - y) > slop;
}
if (isMove){
isMove = true;
if (moveX == 0 && moveY ==0) {
Log.e(TAG,"isMove");
//判断翻得是上一页还是下一页
if (x - downX >0){
isNext = false;
}else{
isNext = true;
}
cancelPage = false;
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
// calcCornerXY(downX,mScreenHeight);
if (mScreenWidth / 2 > downX){
calcCornerXY(mScreenWidth - downX,downY);
}
if (!isNext) {
noNext = true;
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
//上一页滑动不出现对角
if (downX > mScreenWidth / 2){
calcCornerXY(downX,mScreenHeight);
}else{
calcCornerXY(mScreenWidth - downX,mScreenHeight);
}
if (!isPre) {
noNext = true;
return true;
}
}
Log.e(TAG,"isNext:" + isNext);
}else{
//判断是否取消翻页
if (isNext){
if (x - moveX > 0){
cancelPage = true;
}else {
cancelPage = false;
}
}else{
if (x - moveX < 0){
cancelPage = true;
}else {
cancelPage = false;
}
}
Log.e(TAG,"cancelPage:" + cancelPage);
}
moveX = x;
moveY = y;
isRuning = true;
this.postInvalidate();
}
}else if (event.getAction() == MotionEvent.ACTION_UP){
Log.e(TAG,"ACTION_UP");
if (!isMove){
cancelPage = false;
//是否点击了中间
if (downX > mScreenWidth / 5 && downX < mScreenWidth * 4 / 5 && downY > mScreenHeight / 3 && downY < mScreenHeight * 2 / 3){
if (mTouchListener != null){
mTouchListener.center();
}
Log.e(TAG,"center");
// mCornerX = 1; // 拖拽点对应的页脚
// mCornerY = 1;
// mTouch.x = 0.1f;
// mTouch.y = 0.1f;
return true;
}else if (x < mScreenWidth / 2){
isNext = false;
}else{
isNext = true;
}
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
if (!isNext) {
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
calcCornerXY(mScreenWidth - downX,mScreenHeight);
mTouch.y = mScreenHeight;
if (!isPre) {
return true;
}
}
}
if (cancelPage && mTouchListener != null){
mTouchListener.cancel();
}
Log.e(TAG,"isNext:" + isNext);
if (!noNext) {
isRuning = true;
startAnimation(400);
this.postInvalidate();
}
}
return true;
}
public void setTouchListener(TouchListener mTouchListener){
this.mTouchListener = mTouchListener;
}
public interface TouchListener{
void center();
Boolean prePage();
Boolean nextPage();
void cancel();
void showAdAfterAni();
}
private void startAnimation(int delayMillis) {
int dx, dy;
// dx 水平方向滑动的距离,负值会使滚动向左滚动
// dy 垂直方向滑动的距离,负值会使滚动向上滚动
if (cancelPage){
if (mCornerX > 0 && isNext) {
dx = (int) (mScreenWidth - mTouch.x);
} else {
dx = -(int) mTouch.x;
}
if (!isNext){
dx = (int) - (mScreenWidth + mTouch.x);
}
if (mCornerY > 0) {
dy = (int) (mScreenHeight - mTouch.y);
} else {
dy = - (int) mTouch.y; // 防止mTouch.y最终变为0
}
}else {
if (mCornerX > 0 && isNext) {
dx = -(int) (mScreenWidth + mTouch.x);
} else {
dx = (int) (mScreenWidth - mTouch.x + mScreenWidth);
}
if (mCornerY > 0) {
dy = (int) (mScreenHeight - 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();
mTouch.x = mScroller.getFinalX();;
mTouch.y = mScroller.getFinalY();;
postInvalidate();
}
}
public boolean isFinishAnim(){
return mScroller.isFinished();
}
public boolean isRunning(){
return isRuning;
}
/**
* 是否能够拖动过去
*
* @return
*/
public boolean canDragOver() {
if (mTouchToCornerDis > mScreenWidth / 10)
return true;
return false;
}
/**
* 是否从左边翻向右边
*
* @return
*/
public String DragToRight() {
// if (mCornerX > 0)
// return false;
// return true;
if (actiondownX>mScreenWidth/3.0 && actiondownX < (mScreenWidth * 2.0 / 3.0) ) {
Log.d("PageWidget","是否进入此语句");
return "popview";
} else if (actiondownX < mScreenWidth / 3.0) {
Log.d("PageWidget", "mScreenWidth / 3.0=" + mScreenWidth / 3.0);
return "right";
} else if (actiondownX > mScreenWidth*2.0 /3 ) {
return "left";
}
return null;
}
public boolean right() {
if (mCornerX > -4)
return false;
return true;
}
/**
* 绘制翻起页背面
*
* @param canvas
* @param bitmap
*/
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();
try {
canvas.clipPath(mPath0);
canvas.clipPath(mPath1, Region.Op.INTERSECT);
} catch (Exception e) {
}
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();
}
/**
* 绘制翻起页的阴影
*
* @param canvas
*/
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();
try {
canvas.clipPath(mPath0, Region.Op.XOR);
canvas.clipPath(mPath1, Region.Op.INTERSECT);
} catch (Exception e) {
// TODO: handle exception
}
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();
try {
canvas.clipPath(mPath0, Region.Op.XOR);
canvas.clipPath(mPath1, Region.Op.INTERSECT);
} catch (Exception e) {
}
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 - mScreenHeight;
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();
}
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();
try {
canvas.clipPath(mPath0);
canvas.clipPath(mPath1, Region.Op.INTERSECT);
} catch (Exception e) {
}
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,
(int) (mMaxLength + mBezierStart1.y));//左上及右下角的xy坐标值,构成一个矩形
mBackShadowDrawable.draw(canvas);
canvas.restore();
}
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);
try {
canvas.restore();
} catch (Exception e) {
}
}
/**
* 计算拖拽点对应的拖拽脚
*
* @param x
* @param y
*/
public void calcCornerXY(float x, float y) {
// Log.i("hck", "PageWidget x:" + x + " y" + y);
if (x <= mScreenWidth / 2) {
mCornerX = 0;
}else {
mCornerX = mScreenWidth;
}
if (y <= mScreenHeight / 2) {
mCornerY = 0;
} else {
mCornerY = mScreenHeight;
}
if ((mCornerX == 0 && mCornerY == mScreenHeight)
|| (mCornerX == mScreenWidth && mCornerY == 0)) {
mIsRTandLB = true;
}else {
mIsRTandLB = false;
}
}
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);
float f4 = mCornerY-mMiddleY;
if (f4 == 0) {
mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
* (mCornerX - mMiddleX) / 0.1f;
// Log.d("PageWidget",""+f4);
}else {
mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
* (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
// Log.d("PageWidget","没有进入if判断"+ mBezierControl2.y + "");
}
// 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 < mScreenWidth) {
if (mBezierStart1.x < 0 || mBezierStart1.x > mScreenWidth) {
if (mBezierStart1.x < 0)
mBezierStart1.x = mScreenWidth - mBezierStart1.x;
float f1 = Math.abs(mCornerX - mTouch.x);
float f2 = mScreenWidth * 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);
float f5 = mCornerY-mMiddleY;
if (f5 == 0) {
mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
* (mCornerX - mMiddleX) / 0.1f;
}else {
mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
* (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
// Log.d("PageWidget", mBezierControl2.y + "");
}
// 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;
}
/**
* 求解直线P1P2和直线P3P4的交点坐标
*
* @param P1
* @param P2
* @param P3
* @param P4
* @return
*/
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;
}
}