3.2 View的滑动

1. 实现滑动的三种方式

  • 通过View本身提供的scrollTo/scrollBy方法
  • 通过动画给View施加平移效果
  • 通过改变View的LayoutParams使得View重新布局,实现滑动

2. scrollTo/scrollBy

使用:

view.scrollTo(200,200);
view.scrollBy(200,200);

源码:

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);
}

scrollBy实际上是调用了scrollTo方法,他实现的是相对滑动;而scrollTo实现的是绝对滑动。
在滑动过程中,mScrollX的值总是等于View的左边缘和View的内容的左边缘在水平方向的距离,而mScrollY的值等于View上边缘和View内容的上边缘的竖直距离。
View的边缘指View的位置。内容边缘指View中的内容的边缘。scrollTo/scrollBy只能改变View的内容边缘,而不能改变View在布局中的位置。mScrollX和mScrollY的单位是像素,是有正负的。起始位置-终点位置的结果值就是scrollX和scrollY的值,是正就是正,是负就是负。也就是当View左边缘在View内容左边缘的右边时,mScrollX为正。反之为负。

3. 使用动画

objectAnimator = ObjectAnimator.ofFloat(view,"translationX",0,500).setDuration(5000);
objectAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        Log.e("aaa", "x=" + view.getX() + ",y=" + view.getY() + ",translationX=" + view.getTranslationX() + ",translationY=" + view.getTranslationY());
    }

    @Override
    public void onAnimationCancel(Animator animation) {

    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }
});
view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e("aaa", "x=" + view.getX() + ",y=" + view.getY() + ",translationX=" + view.getTranslationX() + ",translationY=" + view.getTranslationY());
        objectAnimator.start();
    }
});

动画启动前打印x,translationX的值,动画结束后,也打印他们的值如下:

x=30.0,y=30.0,translationX=0.0,translationY=0.0 
x=530.0,y=30.0,translationX=500.0,translationY=0.0

前文说过

x=left + translationX

3.0以上的属性动画其位置是随着动画移动了的,而3.0以下的机器由于不支持属性动画,所以位置不随着动画移动,这是动画的主要缺点。

4. 改变布局参数

RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
lp.width+=100;
lp.leftMargin+=100;
view.requestLayout();
// 或者 view.setLayoutParams(lp);

5. 三种方式的比较

  • scrollTo/scrollBy:操作简单,适合对View内容的滑动
  • 动画:操作简单,主要用于没有交互的View或者复杂动画。
  • 改变参数布局:操作稍微复杂,适用于有交互的Veiw

6. 小栗子

public class DemoButton extends Button {
    int mLastX, mLastY;

    public DemoButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                int translationX = (int) getTranslationX() + deltaX;
                int translationY = (int) getTranslationY() + deltaY;
                setTranslationX(translationX);
                setTranslationY(translationY);
                break;
        }
        mLastX = x;
        mLastY = y;
        return true;
    }
}

这个例子其实不用动画,因为move的响应非常快,已经达到了动画要求的梯度值,所以直接设置其值就可以。

你可能感兴趣的:(3.2 View的滑动)