[android学习]View的滑动解析

因为移动设备的屏幕限制,一屏幕的展示往往是不足够的,且在自定义view当中,掌握view的滑动可以使我们实现绚丽的效果,因此掌握view的滑动无论是在日常开发还是创造轮子都是重中之重。

View滑动的三种实现方式:

1,通过View本身提供的scrollTo/scrollBy方法来实现滑动

2,通过动画给View施加平移效果实现滑动

3,通过改变View的LayoutParams使得View重新布局从而实现滑动

 

一:使用scrollTo/scrollBy

通过查看View的源码,可以得知,View类当中提供了scrollTo/scrollBy这两个方法帮助我们实现。

/**
     * Set the scrolled position of your view. This will cause a call to
     * {@link #onScrollChanged(int, int, int, int)} and the view will be
     * invalidated.
     * @param x the x position to scroll to
     * @param y the y position to scroll to
     */
    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();
            }
        }
    }


/**
     * Move the scrolled position of your view. This will cause a call to
     * {@link #onScrollChanged(int, int, int, int)} and the view will be
     * invalidated.
     * @param x the amount of pixels to scroll by horizontally
     * @param y the amount of pixels to scroll by vertically
     */
    public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

从源码得知scrollBy实际上也是调用了scrollTo方法,它实现了基于当前位置的相对滑动,而scrollTo则实现了基于所有传递参数的绝对滑动,它会将当前记录的成员变量mScrollX和mScrollY记录下来,并将要滑动到的新坐标值x,y赋值给mScrollX和mScrollY,最后调用onScrollChanged(mScrollX, mScrollY, oldX, oldY),invalidateParentCaches()这个方法的作用是迫使父控件重建其显示列表,作用是清除父缓存和避免事件失效。

注意:滑动过程中mScrollX和mScrollY的改变规则(可通过getScrollX和getScrollY分别得到)

在滑动过程中,mScrollX总是等于View左边缘和View内容左边缘在水平方向的距离,而mScrollY的值总是等于View上边缘和View内容上边缘在竖直方式的距离。View边缘指的是View的位置,由四个顶点组成,而View内容边缘是指View中的内容的边缘,scrollBy和scrollTo只能改变View内容的位置而不能改变View在布局中的位置。

mScrollX和mScrollY的单位是像素,并且当View左边缘在View内容左边缘的右边时,mScrollX为正值,反之为负(左→右滑动为负值,反之为正);当View的上边缘在View内容上边缘下边时,mScrollY为正,反之为负(上→下 为负,反之为正)。

 

二:使用动画

通过动画可以对一个View进行平移,而平移就是一种滑动。使用动画来移动View,主要是操作View的translationX和translationY属性,既可以采用传统的View动画,也可以采用属性动画,如果使用属性动画需要考虑兼容3.0以下版本(采用开源动画库nineoldandroids)。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true">
    
    <translate
        android:fromXDelta="0"
        android:toXDelta="100"
        android:fromYDelta="0"
        android:toYDelta="100"
        android:duration="100" />
</set>
ObjectAnimator.ofFloat(view, "translationX", 0, 100).setDuration(100).start();

注意:View动画是对View的影像做操作,它并不能真正改变View的位置参数,包括宽高,并且如果希望动画消失后的状态得以保留还必须将fillAfter属性设置为true,否则动画完成后其动画效果会消失。使用属性动画并不会出现上述问题,但是在android3.0以下无法使用属性动画,因此需要使用兼容库,但是通过兼容库实现的属性动画本质仍然是View动画。

因为View动画并不能真正改变View的位置,会带来一个严重的问题,如果我们将一个带点击事件的Button移动了,然后点击它新位置的区域,发现无法触发事件了,而点击原位置是可以触发事件,尽管Button已经不在原始位置了。因为不管Button怎么做变换,它的位置信息(四个顶点和宽/高)并没有随着动画而改变,因此在系统眼中,该Button并没有发生任何改变,它依旧处在原始位置,呈现的只是它的影像。从android3.0开始,使用属性动画可以解决上述问题。

 

三:改变布局参数

即改变LayoutParams。比如我们想把一个View向右平移100px,只需将该View的LayoutParams里的marginLeft参数的值增加100px即可。

MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.width += 100;
params.leftMargin += 100;
view.requestLayout();
//或者view.setLayoutParams(params);

 

上述是实现View滑动的三种实现方式,在开发当中应该根据不同情况去选择适合的方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值