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; } }