专栏名称: Anlia
Android工程师
目录
相关文章推荐
开发者全社区  ·  董事长十几刀刺死 ... ·  16 小时前  
开发者全社区  ·  逆天了,OnlyFans杭州岗 ·  16 小时前  
开发者全社区  ·  55 ... ·  昨天  
开发者全社区  ·  H家最新进展 ·  2 天前  
开发者全社区  ·  没有大于40岁的P7了 ·  2 天前  
51好读  ›  专栏  ›  Anlia

Android自定义View——从零开始实现书籍翻页效果(二)

Anlia  · 掘金  · android  · 2017-12-19 06:42

正文

版权声明:本文为博主原创文章,未经博主允许不得转载

系列教程: Android开发之从零开始系列

源码: AnliaLee/BookPage ,欢迎star

大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论

前言 :在上篇 Android自定义View——从零开始实现书籍翻页效果(一) 博客中,我们实现了 基本的上下翻页效果 右侧最大翻页距离的限制 ,这期我们要将这个view的翻页效果以及动画补齐

本篇只着重于思路和实现步骤,里面用到的一些知识原理不会非常细地拿来讲,如果有不清楚的api或方法可以在网上搜下相应的资料,肯定有大神讲得非常清楚的,我这就不献丑了。本着认真负责的精神我会把相关知识的博文链接也贴出来(其实就是懒不想写那么多哈哈),大家可以自行传送。为了照顾第一次阅读系列博客的小伙伴,本篇会出现一些在之前 系列博客 就讲过的内容,看过的童鞋自行跳过该段即可

国际惯例,先上效果图,本次主要 补全了翻页效果 以及 增加取消翻页的动画


完善右侧最大翻页距离的限制

开讲之前,我先把标识点的位置图贴出来让大家回顾一下

在上篇博客中我们讲了如何限制翻页的最大距离,也就是 c 点的x坐标不能小于0,虽然目的达到了,但是用户体验并不好,可以很明显地观察到当 c 点x坐标处于临界值时,翻页会静止不动,如果此时触摸点大范围移动后,会出现翻页“瞬移”,造成一种卡顿的感觉,如下图

要消除这种“瞬移”的现象,我们要在 c 点x坐标小于0的情况下,让 c 点强制处于临界位置(左下角),然后翻页页角继续跟随触摸点移动的方向移动,要做到这一点得用到一些相似三角形的数学知识,重新计算出 a 点的位置绘制View,先来看下实现的原理(请无视我的渣画工╮(╯▽╰)╭ )

图中我们将 触摸点 标为 a1 ,与 a1 对应的 c 点标为 c1 ,此时 c1 的x坐标是小于0。而 a2 是我们重新计算得到的a点,也就是最后进行绘制的a点,其对应的 c 点标为 c2 c2 位于View的 左下角 (x坐标为0),容易观察到直角 三角形a1 c1 m1 直角三角形a2 c2 m2 相似,此时 f 点位于View的 右下角 (在右上角同理),因此我们可以通过相应的公式计算得到 a2的坐标为(f.x-w2,f.y-h2) ,得到计算 a2 的方法后,我们修改原来的 BookPageView

/**
 * 设置触摸点
 * @param x
 * @param y
 * @param style
 */
public void setTouchPoint(float x, float y, String style){
	switch (style){
		case STYLE_TOP_RIGHT:
			f.x = viewWidth;
			f.y = 0;
			break;
		case STYLE_LOWER_RIGHT:
			f.x = viewWidth;
			f.y = viewHeight;
			break;
		default:
			break;
	}
	a.x = x;
	a.y = y;
	calcPointsXY(a,f);

	MyPoint touchPoint = new MyPoint(x,y);
	if(calcPointCX(touchPoint,f)<0){//如果c点x坐标小于0则重新测量a点坐标
		calcPointAByTouchPoint();
		calcPointsXY(a,f);
	}
	postInvalidate();
}

/**
 * 如果c点x坐标小于0,根据触摸点重新测量a点坐标
 */
private void calcPointAByTouchPoint(){
	float w0 = viewWidth - c.x;

	float w1 = Math.abs(f.x - a.x);
	float w2 = viewWidth * w1 / w0;
	a.x = Math.abs(f.x - w2);

	float h1 = Math.abs(f.y - a.y);
	float h2 = w2 * h1 / w1;
	a.y = Math.abs(f.y - h2);
}

效果如图


添加横向翻页效果

既然我们实现的是仿真的翻页效果,翻页除了从上下两角翻,自然还能横向水平进行翻页。我们先将View划分成上下左右中五个区域,如图

我们根据触摸起始的位置所位于的区域,定义五种不同的手势操作,其中上下(top,low)对应的是上下角进行翻页,左右(left,right)对应的横向水平翻页,中间(middle)则是为了以后作为呼出菜单而保留的区域。为了提高代码复用率和尽可能小的改动,我们实现横向翻页只需将a点的y坐标强制等于View的高度减1即可(当然大家也可以根据自己的需要重新计算横向翻页时的绘制区域,我这里就简单实现了),修改我们的 BookPageView

private String style;
public static final String STYLE_LEFT = "STYLE_LEFT";//点击左边区域
public static final String STYLE_RIGHT = "STYLE_RIGHT";//点击右边区域
public static final String STYLE_MIDDLE = "STYLE_MIDDLE";//点击中间区域
public static final String STYLE_TOP_RIGHT = "STYLE_TOP_RIGHT";//f点在右上角
public static final String STYLE_LOWER_RIGHT = "STYLE_LOWER_RIGHT";//f点在右下角

/**
 * 设置触摸点
 * @param x
 * @param y
 * @param style
 */
public void setTouchPoint(float x, float y, String style){
	MyPoint touchPoint = new MyPoint();
	a.x = x;
	a.y = y;
	this.style = style;
	switch (style){
		case STYLE_TOP_RIGHT:
			f.x = viewWidth;
			f.y = 0;
			calcPointsXY(a,f);
			touchPoint = new MyPoint(x,y);
			if(calcPointCX(touchPoint,f)<0){//如果c点x坐标小于0则重新测量a点坐标
				calcPointAByTouchPoint();
				calcPointsXY(a,f);
			}
			postInvalidate();
			break;
		case STYLE_LEFT:
		case STYLE_RIGHT:
			a.y = viewHeight-1;
			f.x = viewWidth;
			f.y = viewHeight;
			calcPointsXY(a,f);
			postInvalidate();
			break;
		case STYLE_LOWER_RIGHT:
			f.x = viewWidth;
			f.y = viewHeight;
			calcPointsXY(a,f);
			touchPoint = new MyPoint(x,y);
			if(calcPointCX(touchPoint,f)<0






请到「今天看啥」查看全文