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

917 lines
32 KiB
Plaintext
Raw Normal View History

2024-02-06 22:23:29 +08:00
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;
}
}