Android

View基础(二)之滑动

2019-03-30  本文已影响8人  12313凯皇

Android设备上,滑动几乎是应用的标配,不管是下拉刷新还是SlidingMenu,它们的基础都是滑动。从另外一方面来说,Android手机由于屏幕比较小,为了给用户呈现跟多的内容,就需要使用滑动来隐藏和显示一些内容。基于上述两点,可以知道滑动在Android开发中具有很重要的作用。

View的滑动有三种实现方式

下面来一一进行分析。

使用scrollTo/scrollBy

为了实现View的滑动,View提供了专门的方法来实现这个功能,那就是scrollToscrollBy,我们先来看看这两个方法的实现,如下所示:

/**
 * 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则实现了基于所传递参数的绝对滑动。scrollToscrollBy都是改变通过View内部的两个属性mScrollXmScrollY来实现滑动的,这两个属性可以通过getScrollXgetScrollY方法得到,下面先简要概括一下:在滑动过程中,mScrollX的值总是等于View的左边缘和View内容左边缘在水平方向的距离,而mScrollY的值总是等于View上边缘和View内容上边缘在垂直方向的距离。

View边缘是指View的位置,由四个顶点组成,而View内容边缘是指View中的内容的边缘,scrollToscrollBy只能改变View内容的位置而不能改变View在布局中的位置mScrollXmScrollY的单位为像素,并且当View左边缘在View内容左边缘的右边时,mScrollX为正值,反之为负值。换句话说,如果从左向右滑动,那么mScrollX为负值,反之为正值;如果从上往下滑动,那么mScrollY为负值,反之则为正值。

为了更好的理解这个问题,下面举个例子,如下图所示(蓝色表示View的内容)。假设图中水平和竖直方向的滑动距离都为100像素,针对图中各种滑动情况,都给出了对应的mScrollXmScrollY的值。

mScrollX和mScrollY的变化规律示意

使用动画

通过动画我们能够让一个View进行平移,而平移就是一种滑动。使用动画来移动View,主要是操作ViewtranslationXtranslationY属性,既可以采用传统的View动画,也可以采用属性动画

采用View动画的代码如下所示。此动画可以在100ms内将一个View从原始位置向右下角移动100个像素。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <translate
        android:duration="100"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="100"
        android:toYDelta="100"/>

</set>

如果采用属性动画的话,就更简单了,以下代码可以将一个View在100ms内从原始位置向右平移100像素。

ObjectAnimator.ofFloat(targetView,"translationX",0,100)
        .setDuration(100).start();

上面简单介绍了通过动画来移动View的方法,关于动画可以跳转至我的另一篇文章:Android动画(一)之View动画。使用动画来做View的滑动需要注意一点,View动画是对View的影像做操作,它并不能改变View的位置参数,包括宽/高,并且如果希望动画后的状态得以保留还必须将fillAfter属性设置为true,否则动画完成后其动画结果会消失,但是使用属性动画则不会存在这个问题。

上面提到了View动画并不能真正改变View的位置,这会带来一个很严重的问题。比如我们通过View动画将一个Button向右移动100px,并且这个View设置有点击事件,那么当点击原始位置时,它的onclick事件会被触发,单击新位置却不会触发,因为它的位置信息并不会随着动画而改变。如果想要解决这个问题可以改为使用属性动画(Android 3.0之后的版本),或者在新位置创建一个的和原view一样的view,并且默认隐藏,当view滑动之后再将其显示出来并隐藏原来的那个view

改变布局参数

改变布局参数,即改变LayoutParams。例如我们想要将一个Button向右平移100px,我们只需要将这个ButtonLayoutParams里的marginLeft参数的值增加100px即可。下面是示例代码:

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

三种滑动方式的对比

先看scrollTo/scrollBy,它是View提供的原生方法,专门用于View的滑动,但是它只能滑动View的内容,并不能滑动View本身

再看动画,View动画无法改变View本身的属性,所以如果动画元素不需要响应用户的交互,那么使用动画是比较合适的。且动画还有一个很明显的优点:一些复杂的效果必须要通过动画才能实现。

最后来看改变布局方式,它除了使用起来麻烦点外,也明显的区别,它的主要适用对象是一些具有交互性的View

针对以上分析再做一下总结:

  • scrollTo/scrollBy:操作简单,适合对View内容的滑动。
  • 动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果。
  • 改变布局参数:操作稍微复杂,适用于有交互的View
上一篇 下一篇

猜你喜欢

热点阅读