版权声明:本文为博主原创文章,未经博主允许不得转载。
系列教程:Android开发之从零开始系列
源码:github.com/AnliaLee/BookPage,欢迎star大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论
前言:本篇是系列博客的第三篇,这次我们要研究 书籍翻页效果 。不知道大家平时有没用过iReader、掌阅这些小说软件,里面的翻页效果感觉十分的酷炫。有心想研究研究如何实现,于是网上找了找,发现这方面的教学资料非常少,所幸能找到何明桂大大的Android 实现书籍翻页效果—-原理篇这样的入门博客(感谢大大 Orz),我们就以这篇博客为切入点从零实现我们自己的翻页效果。由于这次坑比较深,预计会写好几期,感兴趣的小伙伴可以点下关注以便及时收到更新提醒,谢谢大家的支持 ~
本篇只着重于思路和实现步骤,里面用到的一些知识原理不会非常细地拿来讲,如果有不清楚的api或方法可以在网上搜下相应的资料,肯定有大神讲得非常清楚的,我这就不献丑了。本着认真负责的精神我会把相关知识的博文链接也贴出来(其实就是懒不想写那么多哈哈),大家可以自行传送。为了照顾第一次阅读系列博客的小伙伴,本篇会出现一些在之前系列博客就讲过的内容,看过的童鞋自行跳过该段即可
国际惯例,先上效果图,本次主要实现了基本的上下翻页效果与右侧最大翻页距离的限制
目录
- 计算与绘制各个标识点
- 连接各标识点绘制A、B、C区域
- 测量及自适应View的宽高
- 通过触摸控制各标识点位置
- 限制右侧翻页的最大距离
计算与绘制各个标识点
相关博文链接
在看这篇博客之前,希望大家能先了解一下书籍翻页的实现原理,博客链接我已经贴出来了。通过原理讲解我们知道,整个书籍翻页效果界面分成了三个区域,A为当前页区域,B为下一页区域,C为当前页背面,如图所示
书籍翻页效果的实现就是要以我们触摸屏幕位置的坐标为基础绘制出这三个区域,形成模拟翻页的特效。要绘制这三个区域,我们需要通过一组特定的点来完成,这些点的坐标需要通过两个已知的点(触摸点、相对边缘角)计算得到,下图我将各个特定点的位置和计算公式贴出来,大家对照着原理一起理解(渣画工望体谅 ╮(╯▽╰)╭ ),其中b点是由ae和cj的交点,k点是由ah和cj的交点
简单总结一下,a是触摸点,f是触摸点相对的边缘角,g是af的中点,ab、ak、dj是直线;曲线cdb是起点为c,控制点为e,终点为b的二阶贝塞尔曲线;曲线kij是起点为k,控制点为h,终点为j的二阶贝塞尔曲线,区域A、B、C就由这些点和线划分开来。我们将这些点称为标识点,下一步就是模拟设定a和f点的位置,将这组标识点绘制到屏幕上来验证我们的计算公式是否正确,创建BookPageView
public class BookPageView extends View {
private Paint pointPaint;//绘制各标识点的画笔
private Paint bgPaint;//背景画笔
private MyPoint a,f,g,e,h,c,j,b,k,d,i;
private int defaultWidth;//默认宽度
private int defaultHeight;//默认高度
private int viewWidth;
private int viewHeight;
public BookPageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
private void init(Context context, @Nullable AttributeSet attrs){
defaultWidth = 600;
defaultHeight = 1000;
viewWidth = defaultWidth;
viewHeight = defaultHeight;
a = new MyPoint(400,800);
f = new MyPoint(viewWidth,viewHeight);
g = new MyPoint();
e = new MyPoint();
h = new MyPoint();
c = new MyPoint();
j = new MyPoint();
b = new MyPoint();
k = new MyPoint();
d = new MyPoint();
i = new MyPoint();
calcPointsXY(a,f);
pointPaint = new Paint();
pointPaint.setColor(Color.RED);
pointPaint.setTextSize(25);
bgPaint = new Paint();
bgPaint.setColor(Color.GREEN);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//为了看清楚点与View的位置关系绘制一个背景
canvas.drawRect(0,0,viewWidth,viewHeight,bgPaint);
//绘制各标识点
canvas.drawText("a",a.x,a.y,pointPaint);
canvas.drawText("f",f.x,f.y,pointPaint);
canvas.drawText("g",g.x,g.y,pointPaint);
canvas.drawText("e",e.x,e.y,pointPaint);
canvas.drawText("h",h.x,h.y,pointPaint);
canvas.drawText("c",c.x,c.y,pointPaint);
canvas.drawText("j",j.x,j.y,pointPaint);
canvas.drawText("b",b.x,b.y,pointPaint);
canvas.drawText("k",k.x,k.y,pointPaint);
canvas.drawText("d",d.x,d.y,pointPaint);
canvas.drawText("i",i.x,i.y,pointPaint);
}
/**
* 计算各点坐标
* @param a
* @param f
*/
private void calcPointsXY(MyPoint a,