滑动作为Android中最基础的特效之一,使用场景非常广泛。实现的方式也有多种,理解各种滑动的实现方式。清楚在开发中根据自己的实际需求,选择合理的实现方案。这篇文章从:scrollTo()/scrollBy()内容滑动|动画方式滑动|修改布局参数,三种方式来做简要的分析。
一丶scrollerTo()&&scrollBy()内容滑动
这两个方法都是View自带的滑动方法,即每个控件都可以通过调用这两个方法实现滑动。scrollBy()方法的实现本质也是调用scrollTo()方法,不同之处在于。scrollyTo()方法参数是确定滑动位置的终点,即要滑动到哪儿去,绝对坐标。而scrollBy()方法参数是形容要滑动的距离,要滑动多少,根据当前位置的相对坐标。 下面通过源码来一探究竟:
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
从源码中可以得知scrollTo()方法会先判断起点和终点的位置是否不相同,符合滑动的条件,保存和更新起点坐标,不难理解滑动后终点就成了新的起点。这样就造成了此次滑动完成后,再调用次方法,如果参数终点坐标和起点坐标相同,滑动就不会生效。而scrollBy()方法中直接调用scrollTo方法,将起点坐标位置和滑动的距离相加,确定终点位置,这样终点坐标永远都不会和起点坐标重复,滑动一直有效。举个栗子:
scrollTo()效果 btn_scroll.scrollTo(100,0)
怎么按钮没动,字怎么动了?没错,scrollTo()方法是对View的内容进行滑动,调用Button的scrollTo()方法滑动的是他的字,TextView也是这样,当然Button本质也是基于TextView。当自定义View时,滑动的就是里面的圆丶矩形丶view…… 当Button跑了100像素时,再点击执行scrollTo(100,0)时就没有任何反应了,这就是相对起点的绝对坐标。
scrollBy()效果: btn_scroll.scrollBy(100,0);
一直执行scrollBy(100,0)都是生效的,这就是相对当前位置的相对坐标。结论:scrollTo()和scrollBy()这两种方法是对View的内容进行滑动,并没有改变View真正的布局位置。
二丶动画方式实现滑动
动画方式主要有两种补间动画和属性动画,这两种方式也没有实际改变view布局位置,需要值得注意的是补间动画执行结束后效果会瞬间回到原来的位置,是对影像进行操作,将fillAfter属性改为true就不会有这种效果,属性动画则没有这一特性。举个栗子:
/*补间动画*/
TranslateAnimation animation = new TranslateAnimation(0,300,0,0);
animation.setDuration(2000);
animation.setFillAfter(true);
btn_scroll.startAnimation(animation);
/*属性动画*/
ObjectAnimator animator = ObjectAnimator.ofFloat(btn_scroll,"translationX",0,300);
animator.setDuration(2000).start();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
实现效果:
而补间动画还会有一个问题,当Button滑动完成之后,再点击Button没有任何响应,而点击Button之前的位置仍可以触发onClick()事件,属性动画没有这一特性。
三丶修改布局参数
前面讲到的两种方式都提到并没有真正改变布局参数,这回终于说到改变布局参数而实现。。这种方式是直接改变View在父view中的布局位置,比如要实现上图Button右滑300像素,则将View左边到父View左边的距离Left,View右边到父View左边的距离Right增加300px(对视图坐标系不太清楚的可以参考这篇文章:坐标系),即可实现,举个栗子:
btn_scroll.layout(btn_scroll.getLeft()+300,btn_scroll.getTop(),btn_scroll.getRight()+300,btn_scroll.getBottom());
- 1
效果和上图动画实现大致相同,不同在于动画可以规定在多长时间内完成滑动,而修改布局参数和scrollTo()/scrollBy()方法都是在瞬间完成的!修改布局参数的实现方式有多种,但是原理都是一样的就不一 一说明了。
各种方式比较
这里就直接摘录引用《Android开发艺术探索》中的,大佬总结的比较到位。
先看scrollTo/scrollBy这种方式.它是View提供的原生方法,其作用是专门用于View的滑动,它可以比较简单的实现滑动效果,并且不影响内部元素的单击事件.但是它的缺点也是很显然的,它只能滑动View的内容,不能滑动View本身。
再看动画,通过动画来实现View的滑动,这要分情况.如果是Android3.0以上并采用属性动画,那么采用这种方式没有明显的缺点;如果说是使用View动画或者在Android3.0以下使用属性动画,均不能改变View本身的属性.在实际使用中,如果动画元素不需要响应用户的交互,那么使用动画来做滑动是比较适合的,否则就不太适合.但是动画有一个明显的优点,那就是一些复杂的效果必须通过动画才能实现.。
最后看一下改变布局的这种方式,它除了使用起来麻烦点之外,也没有明显的缺点,它的主要使用对象是一些具有交互性的View,因为这些View需要和用户交互,直接通过动画实现会有问题.所以这个时候我们需要使用直接改变布局参数的方法去实现。
scrollTo/scrollBy:操作简单,适合对View内容的滑动。
动画:操作简单,主要使用于没有交互的View和实现复杂的动画效果。
改变布局参数:操作稍微复杂,适用于有交互的View。