android+动态翻页,android酷炫翻页效果+图形分析

a4c26d1e5885305701be709a3d33442f.png

public class PageWidget extends View {

private static final String TAG = "hmg";

private int mWidth = 480;

private int mHeight = 800;

private int mCornerX = 0; // 拖拽点对应的页脚

private int mCornerY = 0;

private Path mPath0;

private Path mPath1;

Bitmap mCurPageBitmap = null; // 当前页

Bitmap mCurPageBackBitmap = 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; // 是否属于右上左下

// for test

float mMaxLength = (float) Math.hypot(480,

800);

int[] mBackShadowColors;

int[] mFrontShadowColors;

GradientDrawable mBackShadowDrawableLR;

GradientDrawable mBackShadowDrawableRL;

GradientDrawable mFolderShadowDrawableLR;

GradientDrawable mFolderShadowDrawableRL;

GradientDrawable

mFrontShadowDrawableHBT;

GradientDrawable mFrontShadowDrawableHTB;

GradientDrawable mFrontShadowDrawableVLR;

GradientDrawable mFrontShadowDrawableVRL;

private Bitmap mBitmap;

private Canvas mCanvas;

private Paint mBitmapPaint;

Paint paint;

Paint mPaint;

public PageWidget(Context context) {

super(context);

// TODO Auto-generated

constructor stub

mPath0 = new Path();

mPath1 = new Path();

createDrawable();

//

---------------------------------------

mBitmap =

Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);

mCanvas = new

Canvas(mBitmap);

mBitmapPaint = new

Paint(Paint.DITHER_FLAG);

paint = new Paint();

mPaint = new Paint();

mPaint.setStyle(Paint.Style.FILL);

mCurPageBitmap =

BitmapFactory.decodeResource(this.getResources(),

R.drawable.page1);

mNextPageBitmap =

BitmapFactory.decodeResource(this.getResources(),

R.drawable.page2);

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

cm.set(array);

mColorMatrixFilter = new

ColorMatrixColorFilter(cm);

mMatrix = new

Matrix();

}

private void calcCornerXY(float x, float y)

{

if (x <= mWidth

/ 2)

mCornerX =

0;

else

mCornerX =

mWidth;

if (y <= mHeight

/ 2)

mCornerY =

0;

else

mCornerY =

mHeight;

if ((mCornerX == 0

&& mCornerY == mHeight)

||

(mCornerX == mWidth && mCornerY ==

0))

mIsRTandLB =

true;

else

mIsRTandLB =

false;

}

@Override

public boolean onTouchEvent(MotionEvent event)

{

// TODO Auto-generated method

stub

if (event.getAction() ==

MotionEvent.ACTION_MOVE) {

mCanvas.drawColor(0xFFAAAAAA);

mTouch.x =

event.getX();

mTouch.y =

event.getY();

this.postInvalidate();

}

if (event.getAction() ==

MotionEvent.ACTION_DOWN) {

mCanvas.drawColor(0xFFAAAAAA);

mTouch.x =

event.getX();

mTouch.y =

event.getY();

calcCornerXY(mTouch.x,

mTouch.y);

this.postInvalidate();

}

if (event.getAction() ==

MotionEvent.ACTION_UP) {

mCanvas.drawColor(0xFFAAAAAA);

mTouch.x =

mCornerX;

mTouch.y =

mCornerY;

this.postInvalidate();

}

// return

super.onTouchEvent(event);

return true;

}

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;

}

private void calcPoints() {

mMiddleX = (mTouch.x +

mCornerX) / 2;

mMiddleY = (mTouch.y +

mCornerY) / 2;

Log.i("Log",mTouch.x+"----------------x");

Log.i("Log",mTouch.y+"----------------y");

Log.i("Log",mCornerX+"----------------cornerX");

Log.i("Log",mCornerY+"----------------cornerY");

//贝塞尔曲线的控制点的横坐标

mBezierControl1.x = mMiddleX -

(mCornerY - mMiddleY)

*

(mCornerY - mMiddleY) / (mCornerX - mMiddleX);

mBezierControl1.y =

mCornerY;

Log.i("Log",mBezierControl1.x+"----------------mBezierControl1X");

Log.i("Log",mBezierControl1.y+"----------------mBezierControl1Y");

mBezierControl2.x =

mCornerX;

mBezierControl2.y = mMiddleY -

(mCornerX - mMiddleX)

*

(mCornerX - mMiddleX) / (mCornerY - mMiddleY);

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 (mBezierStart1.x

< 0 || mBezierStart1.x > 480) {

Log.i("Log","page

move");

if

(mBezierStart1.x <

0) mBezierStart1.x

= mWidth - mBezierStart1.x;

float f1 =

Math.abs(mCornerX - mTouch.x);

float f2 =

mWidth * 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);

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

}

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

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();

canvas.clipPath(mPath0);

canvas.clipPath(mPath1,

Region.Op.INTERSECT);

canvas.drawBitmap(bitmap, 0, 0,

null);

canvas.rotate(mDegrees,

mBezierStart1.x, mBezierStart1.y);

mBackShadowDrawable.setBounds(leftx,

(int) mBezierStart1.y, rightx,

(int)

(mMaxLength + mBezierStart1.y));

mBackShadowDrawable.draw(canvas);

canvas.restore();

}

public void setBitmaps(Bitmap bm1, Bitmap bm2,

Bitmap bm3) {

mCurPageBitmap = bm1;

mCurPageBackBitmap = bm2;

mNextPageBitmap = bm3;

}

@Override

protected void onDraw(Canvas canvas) {

Log.i("Log","onDraw");

canvas.drawColor(0xFFAAAAAA);

calcPoints();

drawCurrentPageArea(mCanvas,

mCurPageBitmap, mPath0);

drawNextPageAreaAndShadow(mCanvas,

mNextPageBitmap);

drawCurrentPageShadow(mCanvas);

drawCurrentBackArea(mCanvas,

mCurPageBitmap);

canvas.drawBitmap(mBitmap, 0,

0, mBitmapPaint);

}

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

}

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();

canvas.clipPath(mPath0,

Region.Op.XOR);

canvas.clipPath(mPath1,

Region.Op.INTERSECT);

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();

canvas.clipPath(mPath0,

Region.Op.XOR);

canvas.clipPath(mPath1,

Region.Op.INTERSECT);

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

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 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();

canvas.clipPath(mPath0);

canvas.clipPath(mPath1,

Region.Op.INTERSECT);

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();

}

}

上面是定义的翻页控件PageWidget

想要测试这个控件很简单定义一个activity

代码如下:

public void onCreate(Bundle

savedInstanceState) {

super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(

WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);

setContentView(new PageWidget(this));

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值