Kotlin进阶-5-View的滑动与动画

目录

1、View位置信息---left、translationX、x

2、滑动位置---MotionEvent和TouchSlop

3、滑动速度---VelocityTracker

4、手势检测---GestureDetector

5、View滑动方式1---ScrollTo/ScrollBy

6、View滑动方式2---动画

6.1、传统动画实现方式一

6.2、传统动画实现方式二

6.3、属性动画

7、View滑动方式3---改变布局参数

8、View滑动三种方式对比

9、弹性滑动---过渡动画

9.1、Scroller

9.2、动画

9.3、Handler#postDelayed


1、View位置信息---left、translationX、x

在Android 中View的位置由四个属性来决定: left、top、right、bottom。

  • left: View 左上顶点相对于父容器的长度
  • top: View 左上顶点相对于父容器的高度
  • right: View 右下顶点相对于父容器的长度
  • bottom: View 右下顶点相对于父容器的高度

注意:x、y轴的起始点为父容器的左上角。

从 Android 3.0 开始,View 增加了 x,y,translationX 和 translationY。

x,y 同样是 View 左上角相对父容器的坐标,但不同于 left 和 top ,这两个坐标点的值并一定都是相等的。而不相等的情况是由 translationX 和 translationY 值的设置引起的。

translationX 和 translationY 是 View 在做完动画移动后左上角相对父容器左上角的偏移量,translationX 和 translationY 默认值都为 0。view动画移动后,x、left、translationX之间的关系如下:

                                     x = left + translationX

如下图:红色框是一个LinearLayout,内部绿色框是一个ImageView,正常情况下ImageView是居中的,当我设置translationX值之后,它就会移动。

                     

2、滑动位置---MotionEvent和TouchSlop

在Android中,我们可以通过OnTouchListener时间来监听 用户的触摸手机的事件:点击、滑动、长按等,同时它会返回一个MotionEvent的参数,通过MotionEvent可以获取我们点击的位置。

x和y返回的是相对于你点击的view左上角的x、y坐标;

rawX和rawY是相对于手机屏幕左上角的x、y坐标。

TouchSlop是系统所能识别出的被认为是滑动的最小距离,换句话说,如果你手指在屏幕上滑动的距离小于TouchSlop常量的话,系统认为你没有做滑动操作。

我们开发中,也可以通过这个常量来忽略掉一些 很小的滑动操作。

这个常量可以通过ViewConfiguration.get(this).scaledTouchSlop获取到

3、滑动速度---VelocityTracker

VelocityTracker是用来进行速度追踪的,用于获取手指滑动屏幕的速度,它的实现方式如下:

需要注意的时候,在进行红色框中的速度获取之前,必须传入你要计算的速度的时间单位。也就是调用绿色框中computeCurrentVelocity(100)方法,参数单位是毫秒,这里我计算的是,100ms内滑动的速度。计算公式如下:

                     速度=(终点位置-起点位置)/100毫秒              结果=100毫秒滑过的像素数   

当我们不使用的时候,应该进行重置并且回收内存。

注意:想要获取速度,监听的View,必须是可以滑动的View,比如RecyclerView、ScrollView。

4、手势检测---GestureDetector

GestureDetector是用来对用户操作行为进行检测和判断的。它的实现过程就是下图红色框的操作就可以了。

它的内部方法有6种,如下图蓝色框

GestureDetector除了监听上面的6种事件以外,还能监听双击相关的操作。

它的实现只要在上面的detector对象上set一下双击的监听事件就可以了。

5、View滑动方式1---ScrollTo/ScrollBy

对于View的滑动我们可以通过ScrollTo/ScrollBy来实现,下面是它们的源码:

从上面的源码看到ScrollBy调用了ScrollTo。

ScrollBy和ScrollTo滑动的是内容的位置,不会改变该View的布局位置,从下面的“你好啊”就能知道,因为它的背景色没有移动,移动的只是“你好啊”。

             

ScrollBy实现的是基于当前位置的相对滑动,ScrollTo实现的是基于传递参数的绝对移动。

从下面的输出结果可以看出,我们view在滑动之前scrollX、Y都为0,当我们滑动后scrollX、Y值改变。

蓝色框:scrollTo--滑动的是绝对位置,多次触发以后,scrollX、Y值不变,也不会有滑动效果

绿色框:scrollBy---滑动的相对位置,多次触发以后,scrollX、Y值累加,view在一直滑动

6、View滑动方式2---动画

Android中动画分为两大类:传统动画和属性动画, 传统动画又分为:帧动画和补间动画。

这里我们通过补间动画来实现View的滑动效果。

6.1、传统动画实现方式一

在anim资源文件夹中创建动画资源文件,然后在代码中调用即可。

6.2、传统动画实现方式二

第二种实现方式就是动态实现了。

注意1: 如果你想要动画移动后,保持移动后的位置,就需要设置fillAfter=true,否则在动画变化完之后,该View会恢复到动画之前的位置。

注意2:传统动画只改变的是该View的影像位置,它的真身其实没有变化,如果你对该View设置了点击的监听事件,你点击动画后的位置是没有反应的,你只有点击它的真身位置才行。

上面的scrollTo和scrollBy也只是改变了内容的位置,它的真身和背景色都不会变化。

针对这个问题,我们可以在可以创建一个和动画View一摸一样的View,同时具有相同的点击事件,当我们完成动画的一刹那,隐藏动画View,显示我们它的假身。

              

6.3、属性动画

上面我们说了传统动画只能改变View的影像位置,它的真身其实还在原处,但是我们的属性动画能真正的移动我们View,也就是说你对View进行完属性动画后,你点击该View,它自身的点击事件会被触发, 但是传统动画,你点击它的动画后的位置,是没有反应的。

属性动画的实现如下图:

7、View滑动方式3---改变布局参数

改变布局参数的移动效果,移动的也是View的真身。

               

8、View滑动三种方式对比

scorllTo/scrollBy:实现简单,没有中间过渡动画效果;但是只有内容位置变化,其View本身的布局位置不会变化;

传统动画:实现简单,有中间过渡动画效果;但是只会改变影像位置,有交互的话,不建议使用;

属性动画:实现简单,有中间过渡动画效果;可以改变View的位置,可以用于有交互的View,但是只能在Android3.0以后使用;对于3.0一下的版本可以使用nineoldandroids这个库来弥补。

改变布局参数:实现稍微复杂,没有中间过渡动画效果;但是对于有交互的View来说,可以用该方法实现。

9、弹性滑动---过渡动画

上面讲解了View滑动的三种方式,其中除了动画的方式带有中间的过渡滑动效果以外,其他两种方式都是没有过渡效果的,它们都是直接跳到了指定的位置。这种用户体验的方式很明显不是很好。

实现带有过渡效果的滑动动画的方式有三种:

1、使用Scroller;

2、使用动画

3、Handler#postDelayed+Thread#sleep

那么接下来,我们首先讲解怎样利用Scroller让scorllTo实现带有过渡动画的滑动效果。

9.1、Scroller

要想让scorllTo实现带有过渡动画的滑动效果,首先需要重写View。

它的实现如下图:

我们来看一下Scoller的startScroll()的源码,我们会发现这里没有做任何的开始动画的操作,只有赋值操作。

那么哪里实现了过渡动画呢?

答案在startScroll()下面的invalidate()方法,当我们重新绘制该View的时候,会触发绿色框内的computeScroll()方法,然后该方法会触发mScroller.computeScrollOffset(),该方法内部会根据时间计算出你当前View要滑动的距离,然后在重新调用postInvalidate()方法,重新绘制该View,然后再重新触发computeScroll()方法。

这样我们的view会在1000毫秒内,不断地重新绘制我们的View,这样就实现了过渡动画的效果。

9.2、动画

对于动画,是自带过渡效果的,所以我们可以直接使用就行。

但是对于scrollTo,我们可以利用属性动画来实现相同的效果。

9.3、Handler#postDelayed

下面除了可以使用Handler#postDelayed实现过渡动画以外,还可以使用View#postDelayed方法,或者使用Thread#sleep实现,实现的思路都一样。

原创文章 120 获赞 34 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/105810226