Android自定义View——从零开始实现书籍翻页效果(二)
来源:互联网 发布:音效软件 知乎 编辑:程序博客网 时间:2024/05/29 09:46
版权声明:本文为博主原创文章,未经博主允许不得转载。
系列教程:Android开发之从零开始系列
源码:github.com/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){//如果c点x坐标小于0则重新测量a点坐标 calcPointAByTouchPoint(); calcPointsXY(a,f); } postInvalidate(); break; default: break; }}
在Activity中监听触摸操作
public class PageActivity extends AppCompatActivity { private BookPageView bookPageView; private String style = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_page); bookPageView = (BookPageView) findViewById(R.id.view_book_page); bookPageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: float x = event.getX(); float y = event.getY(); float width = bookPageView.getViewWidth(); float height = bookPageView.getViewHeight(); if(x<=width/3){//左 style = bookPageView.STYLE_LEFT;// Toast.makeText(PageActivity.this,"点击了左部",Toast.LENGTH_SHORT).show(); bookPageView.setTouchPoint(x,y,style); }else if(x>width/3 && y<=height/3){//上 style = bookPageView.STYLE_TOP_RIGHT;// Toast.makeText(PageActivity.this,"点击了上部",Toast.LENGTH_SHORT).show(); bookPageView.setTouchPoint(x,y,style); }else if(x>width*2/3 && y>height/3 && y<=height*2/3){//右 style = bookPageView.STYLE_RIGHT;// Toast.makeText(PageActivity.this,"点击了右部",Toast.LENGTH_SHORT).show(); bookPageView.setTouchPoint(x,y,style); }else if(x>width/3 && y>height*2/3){//下 style = bookPageView.STYLE_LOWER_RIGHT;// Toast.makeText(PageActivity.this,"点击了下部",Toast.LENGTH_SHORT).show(); bookPageView.setTouchPoint(x,y,style); }else if(x>width/3 && x<width*2/3 && y>height/3 && y<height*2/3){//中 style = bookPageView.STYLE_MIDDLE;// Toast.makeText(PageActivity.this,"点击了中部",Toast.LENGTH_SHORT).show();// bookPageView.setTouchPoint(x,y,bookPageView.STYLE_MIDDLE); } break; case MotionEvent.ACTION_MOVE: bookPageView.setTouchPoint(event.getX(),event.getY(),style); break; case MotionEvent.ACTION_UP: bookPageView.setDefaultPath(); break; } return false; } }); }}
效果如图
增加取消翻页的动画
android scroller类的使用
Android学习之 Scroller的介绍与使用
Android Scroller完全解析,关于Scroller你所需知道的一切
Android – Interpolator
android动画 之Interpolator类
因为我们还没实现将书籍内容导入View中,所以我们先来实现取消翻页的动画效果。这里我们结合Scroller和Interpolator插值器,实现当我们手指离开屏幕时,a点能自动滑落到右下角(右上角)的效果,有关Scroller和Interpolator方面的知识,我将相关博客链接贴出来了,大家可以相互对照着理解,我就不详细阐述了。修改BookPageView
private Scroller mScroller;private void init(Context context, @Nullable AttributeSet attrs){ //省略部分代码... mScroller = new Scroller(context,new LinearInterpolator());//以常量速率滑动即可}@Overridepublic void computeScroll() { if (mScroller.computeScrollOffset()) { float x = mScroller.getCurrX(); float y = mScroller.getCurrY(); if(style.equals(STYLE_TOP_RIGHT)){ setTouchPoint(x,y,STYLE_TOP_RIGHT); }else { setTouchPoint(x,y,STYLE_LOWER_RIGHT); } if (mScroller.getFinalX() == x && mScroller.getFinalY() == y){ setDefaultPath();//重置默认界面 } }}/** * 取消翻页动画,计算滑动位置与时间 */public void startCancelAnim(){ int dx,dy; //让a滑动到f点所在位置,留出1像素是为了防止当a和f重叠时出现View闪烁的情况 if(style.equals(STYLE_TOP_RIGHT)){ dx = (int) (viewWidth-1-a.x); dy = (int) (1-a.y); }else { dx = (int) (viewWidth-1-a.x); dy = (int) (viewHeight-1-a.y); } mScroller.startScroll((int) a.x, (int) a.y, dx, dy, 400);}
在Activity中监听手指抬起操作
case MotionEvent.ACTION_UP: bookPageView.startCancelAnim(); break;
效果如图
至此本篇教程就告一段落了,这期比较短,主要是对上期的补充。下期会实现书籍内容填充或者绘制阴影,看情况吧๑乛◡乛๑。如果大家看了感觉还不错麻烦点个赞,你们的支持是我最大的动力~
- Android自定义View——从零开始实现书籍翻页效果(二)
- Android自定义View——从零开始实现书籍翻页效果(一)
- Android自定义View——从零开始实现书籍翻页效果(三)
- Android自定义View——从零开始实现书籍翻页效果(四)
- Android自定义View——从零开始实现书籍翻页效果(性能优化篇)
- Android自定义View——从零开始实现覆盖翻页效果
- Android自定义View——从零开始实现雪花飘落效果
- Android 实现书籍翻页效果(原理)
- Android 实现书籍翻页效果
- Android 实现书籍翻页效果
- Android 实现书籍翻页效果
- Android 实现书籍翻页效果
- Android 实现书籍翻页效果
- Android实现书籍翻页效果
- Android自定义View——从零开始实现可暂停的旋转动画效果
- Android 实现书籍翻页效果----原理篇
- Android 实现书籍翻页效果----源码篇
- Android 实现书籍翻页效果----完结篇
- python连接hiveserver2
- ImageView图片的自动轮播
- resultype四种之一默认的resultType
- 让更多的人认真的听音乐,Hidizs AP200国内首发上线
- 2013ICPC长春 HDU 4814 Golden Radio Base 乱搞
- Android自定义View——从零开始实现书籍翻页效果(二)
- 文本输入
- Linux虚拟机Apache服务器配置
- MySql 关于存储 emoji表情
- protel 99se 负片打印
- 梯度弥散和梯度爆炸
- 页面往后台传数据中文乱码解决方法
- IDA 使用笔记
- echarts3标题点击取消显示时保留一项显示