654 lines
24 KiB
Plaintext
654 lines
24 KiB
Plaintext
|
package com.novelbook.android.view.animation;
|
|||
|
|
|||
|
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.os.Build;
|
|||
|
import android.widget.Scroller;
|
|||
|
|
|||
|
|
|||
|
public class SimulationAnimation extends AnimationProvider {
|
|||
|
private int mCornerX = 1; // 拖拽点对应的页脚
|
|||
|
private int mCornerY = 1;
|
|||
|
private Path mPath0;
|
|||
|
private Path mPath1;
|
|||
|
|
|||
|
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;
|
|||
|
|
|||
|
public SimulationAnimation(Bitmap mCurrentBitmap, Bitmap mNextBitmap, int width, int height) {
|
|||
|
super(mCurrentBitmap, mNextBitmap, width, height);
|
|||
|
|
|||
|
mPath0 = new Path();
|
|||
|
mPath1 = new Path();
|
|||
|
mMaxLength = (float) Math.hypot(mScreenWidth, mScreenHeight);
|
|||
|
mPaint = new Paint();
|
|||
|
mPaint.setStyle(Paint.Style.FILL);
|
|||
|
|
|||
|
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();
|
|||
|
|
|||
|
mTouch.x = 0.01f; // 不让x,y为0,否则在点计算时会有问题
|
|||
|
mTouch.y = 0.01f;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void drawMove(Canvas canvas) {
|
|||
|
if (getDirection().equals(Direction.next)) {
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void drawStatic(Canvas canvas) {
|
|||
|
if (getCancel()){
|
|||
|
canvas.drawBitmap(mCurPageBitmap, 0, 0, null);
|
|||
|
}else {
|
|||
|
canvas.drawBitmap(mNextPageBitmap, 0, 0, null);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void setCancel(boolean isCancel) {
|
|||
|
super.setCancel(isCancel);
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void startAnimation(Scroller scroller) {
|
|||
|
int dx, dy;
|
|||
|
// dx 水平方向滑动的距离,负值会使滚动向左滚动
|
|||
|
// dy 垂直方向滑动的距离,负值会使滚动向上滚动
|
|||
|
if (getCancel()){
|
|||
|
if (mCornerX > 0 && getDirection().equals(Direction.next)) {
|
|||
|
dx = (int) (mScreenWidth - mTouch.x);
|
|||
|
} else {
|
|||
|
dx = -(int) mTouch.x;
|
|||
|
}
|
|||
|
|
|||
|
if (!getDirection().equals(Direction.next)){
|
|||
|
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 && getDirection().equals(Direction.next)) {
|
|||
|
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
|
|||
|
}
|
|||
|
}
|
|||
|
scroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy, duation);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@Override
|
|||
|
public void setDirection(Direction direction) {
|
|||
|
super.setDirection(direction);
|
|||
|
switch (direction){
|
|||
|
case pre:
|
|||
|
//上一页滑动不出现对角
|
|||
|
if (myStartX > mScreenWidth / 2){
|
|||
|
calcCornerXY(myStartX,mScreenHeight);
|
|||
|
}else{
|
|||
|
calcCornerXY(mScreenWidth - myStartX,mScreenHeight);
|
|||
|
}
|
|||
|
break;
|
|||
|
case next:
|
|||
|
if (mScreenWidth / 2 > myStartX){
|
|||
|
calcCornerXY(mScreenWidth - myStartX,myStartY);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void setStartPoint(float x, float y) {
|
|||
|
super.setStartPoint(x, y);
|
|||
|
calcCornerXY(x,y);
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void setTouchPoint(float x, float y) {
|
|||
|
super.setTouchPoint(x, y);
|
|||
|
//触摸y中间位置吧y变成屏幕高度
|
|||
|
if ((myStartY > mScreenHeight / 3 && myStartY < mScreenHeight * 2 / 3) || getDirection().equals(Direction.pre)){
|
|||
|
mTouch.y = mScreenHeight;
|
|||
|
}
|
|||
|
|
|||
|
if (myStartY > mScreenHeight / 3 && myStartY < mScreenHeight / 2 && getDirection().equals(Direction.next)){
|
|||
|
mTouch.y = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 创建阴影的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);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 是否能够拖动过去
|
|||
|
*
|
|||
|
* @return
|
|||
|
*/
|
|||
|
public boolean canDragOver() {
|
|||
|
if (mTouchToCornerDis > mScreenWidth / 10)
|
|||
|
return true;
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
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);
|
|||
|
// mPaint.setAlpha(0x90);
|
|||
|
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();
|
|||
|
if(Build.VERSION.SDK_INT >= 26){
|
|||
|
// canvas.clipPath(path); //将正面变空白了
|
|||
|
}else {
|
|||
|
// 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;
|
|||
|
}
|
|||
|
}
|