View的滑动之ScrollTo和ScrollBy

目前View滑动的实现方式主要有三种:

1.通过View自身提供的ScrollTo和ScrollBy。

2.通过动画来使View平移来实滑动。

3.第三种是通过改变View的LayoutParams,使View重新布局实现滑动。

这几天在看View的滑动,虽然ScrollTo和ScrollBy在实际的开发过程中用到的很少,特别是属性动画的广泛运用后,既然存在,必有价值。

所以在这里将ScrollTo和ScrollBy简单分析一下:


先看一下ScrollTo的源码:

/**
     * 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();
            }
        }
    }
再看看ScrollBy的源码:

/**
     * 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呢,他们的区别就在于ScrollBy方法中调用ScrollTo时将传递的参数加上了当前 View内容View边缘位置的距离 (mScrollX、mScrollY)。

关于mScrollTo和mScrollBy这里我是这样理解的:

mScrollX    是View左边缘与View内容左边缘的水平方向上的距离,理解为View左边缘X坐标减去View内容左边缘X坐标。

mScrollY    是View顶部与View内容上边缘的在竖直方向上的距离,理解为View顶部Y坐标减去View内容顶部Y坐标。

我们用两幅图来表示:绿色部分为View的内容,框就是View本身。

这里大概能将mScrollX和mScrollY的取值表述清楚了。


下面用一个Demo演示一下ScrollTo和ScrollBy的区别:

Activity:

package com.example.xuzhenhao.myapplication.ui;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.xuzhenhao.myapplication.R;

public class TestActivity extends AppCompatActivity {

    private RelativeLayout rl;
    private TextView tvTo;
    private TextView tvBy;
    private int x = -5;
    private int y = -5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        initView();
    }

    /**
     * 初始化控件
     */
    private void initView() {

        rl = (RelativeLayout) findViewById(R.id.scroll_rl);
        tvTo = (TextView) findViewById(R.id.scroll_tv);
        tvTo.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action){
                    case MotionEvent.ACTION_DOWN:
                        rl.scrollTo(x,y);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }

                return false;
            }
        });
        tvBy = (TextView) findViewById(R.id.scroll_by_tv);
        tvBy.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                switch (action){
                    case MotionEvent.ACTION_DOWN:
                        rl.scrollBy(x,y);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return false;
            }
        });
    }
}

XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scroll_rl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.xuzhenhao.myapplication.ui.TestActivity">

    <TextView
        android:id="@+id/scroll_to_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/dark"
        android:textSize="16sp"
        android:text="ScrollTo"/>

    <TextView
        android:id="@+id/scroll_by_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/scroll_to_tv"
        android:textColor="@color/dark"
        android:textSize="16sp"
        android:text="ScrollBy"/>


</RelativeLayout>

运行起来如下图所示:

我们发现ScrollTo只能移动一次,再次点击就不能移动了,而点击ScrollBy每次都能移动,玄机在哪里??刚刚放出的源码里面已经写的很清楚了。


ScrollTo第一次传参时将传入的形参分别赋值给mScrollX和mScrollY,而每次都会去判断mScrollX和mScrollY与传入的形参是否相等,如果相等就不会去移动。


ScrollBy方法内部调用ScrollTo,在调用ScrollTo时传入的参数为当前View内容的左边缘和顶部到View的左边缘和顶部的距离加上传入的形参,就相当于每次都实现了基于当前位置的相对滑动

注意:

ScroolTo和ScrollBy都只能移动View的内容,View本身是不会移动的,上图中两个View之所以跑了是因为我们是使用最外层布局RelativeLayout的ScrollTo和ScrollBy


感谢!

在此任玉刚的《Android开发艺术探索》第3章第二节View的滑动


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值