Android View的滑动效果

View的滑动效果可分为两类:
    1.View本身的位置不变,View内部的内容滑动;
    2. View的位置发生变化,View作为一个整体滑动;
##.View内部内容的滑动
1.通过以下View的以下两个API方法可实现滑动:
    scrollTo(int x, int y);//滑动到坐标值x、y的位置,初始时x=0,y=0。
                                   //从右向左滑动x增大,从下向上滑动y增大。反之减小。
    scrollBy(int x, int y);//水平、竖直滑动一段长度为x、y的距离;
                                   //从右向左滑动x是正值,从下向上滑动y是正值。反之是负值。

这里的x是View的左边缘相对于内容区左边缘的位移,y是View的上边缘相对于内容区上边缘的位移。

因此,x/y的正负与内容区滚动的方向正好相反。

2.使用Scroller实现弹性滑动,即平滑的滚动:
    Scroller的效果其实与插值器差不多,其主要作用其实是不断通过已滚动的时长来计算出需要滚到到的坐标,滚动其实还是scrollTo()来完成的,Scroller只是简便了位置的计算逻辑而已。
    具体原理,是通过startScroll()设置好滚动的起始x/y位置、滚动x/y长度、滚动时长,然后不断调用其computeScrollOffset()方法,根据当前已经滚动的时长计算出应该滚动到的位置坐标,使用scrollTo(int x, int y)滚动到指定位置,从而达到平滑滚动的效果。
    其实理论上,完全可以自己通过Handler延迟消息或差值器结合Scroller来触发这个循环链条,从而实现弹性滑动。(当然我们也可以连Scroller也不用,位置计算逻辑也由自己来实现。)
    但View内部有一种更方便的实现方法,一般都会使用这种方式,示例代码和注释如下:
public class ScrollTextView extends AppCompatTextView {
    public ScrollTextView(Context context) {
        super(context);
    }

    public ScrollTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private Scroller mScroller = new Scroller(getContext());
    //平滑地水平滚动,在指定时间内,从当前位置滚动到指定的x坐标位置
    public void startSmoothScrollHorizental(int desX, int ms){
        //获取View的内容当前已经偏移的坐标值
        int startX = getScrollX();
        int startY = getScrollY();
        //该方法其实只是为Scroller设定内部的一些值
        //        stratScroll(x起始坐标,y起始坐标,x方向偏移值,y方向偏移值,滚动时长)
        mScroller.startScroll(startX, startY, desX-startX, 0, ms);
        //触发View的重新绘制
        invalidate();
    }

    //需要重写computeScroll()方法,以达到链式不断触发scrollTo()方法,实现平滑滚动的效果:
    //每次invalidate()会触发draw(),而draw()会触发computeScroll()方法;
    //而computeScroll()方法中,会判断滚动是否已结束,
    //    只要未结束,就会触发scrollTo()来实现滚动,然后用postInvalidate()触发invalidate();
    //.......不断循环,链式触发下去.........
    @Override
    public void computeScroll() {
        //Scroller的computeScrollOffset()有两个作用:
        //1.通过判断滚动时长是否已达到设定的时长,来判断是否应该继续滚动下去,
        //                  并返回结果,true:应继续滚动,false:应停止滚动。
        //2.通过 当前已滚动时长/设定的滚动时长比值,结合开启坐标、滑动长度,计算出当前应该滚动到的位置。
        //              该位置坐标值可通过Scroller的getCurrX()、getCurrY()获取到
        if(mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }
}
##.View整体的滑动
1.可使用属性动画移动View的位置。注意:改变的是translationX、translationY以及View当前位置的值,View的原始位置并未改变。
例如:在100ms内从左向右平移100像素
ObjectAnimator.ofFloat(mTvTop, "translationX", 0, 100)
        .setDuration(100).start();
2.可使用Handler或差值器,渐进修改LayoutParams参数中margin值、尺寸等,实现滑动效果。
    

猜你喜欢

转载自blog.csdn.net/u013914309/article/details/124594509