更好地理解 scrollBy() / scrollTo()

scrollTo()与scrollBy()是View提供于实现滑动的方法,其中scrollBy()内部调用了scrolTo()。scrollTo()是移动到具体座标,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);
    }

 /**
     * 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();
            }
        }
    }

  首先我们要清楚,这两个方法滑动的是View的内容。为了更好地理解,请看下面例子。

  在布局中设置一个TextView,给它设置文字,宽高(文字不要充满宽高),再设置一个按钮,当点击按钮时,TextView调用         scrollBy()。代码如下:

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="15dp"
    tools:context=".MainActivity">
   <TextView
       android:id="@+id/tv_scroll"
       android:layout_gravity="center"
       android:text="我是TextView"
       android:textColor="#000000"
       android:textSize="28sp"
       android:background="#B4AFAF"
       android:layout_width="200dp"
       android:layout_height="200dp" />
    <Button
        android:id="@+id/bt_scroll"
        android:layout_gravity="center"
        android:text="scrollBy"
        android:textSize="20sp"
        android:textAllCaps="false"
        android:layout_width="200dp"
        android:layout_height="80dp" />
</LinearLayout>

 MainActivity代码:

public class MainActivity extends AppCompatActivity  {
   TextView tv;
   Button bt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv_scroll);
        bt = findViewById(R.id.bt_scroll);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv.scrollBy(0,-10);
            }
        });
    }

}

 效果如下:

可以看到,TextView调用scrollBy()方法,本身位置并没有移动,移动的是文字内容,即View的内容,我理解为View的画布,由于文字是绘制在画布上的,移动画布,文字也跟着移动了。

上面代码中我们调用scrollBy(0,-10),文字往下移动,这似乎与我们预想的不同。我们都知道android座标系中均为左负右正,上负下正,正常情况下,y方向输入-10,应该往上移动,但结果却相反。这就是scrollTo(0 / scrollBy() 比较难理解的地方。

如何理解呢,经过上面的例子我们知道scrollBy / scrollTo()移动的是View的内容,那么scrollTo()所传入的座标以及scrollBy()传入的偏移量,所作用的应该也是View的内容(画布),下面用两张图来帮助理解。在一开始,view的内容还没移动时,画布的(0,0)座标是与View边框的左上角对齐。(绿色方框表示View的大小,其余表示画布)

   

当调用scrolTo(-15,-10)时,会将画布的(-15,-10)座标与View边框的左上角对齐。(移动是画布,TextView不动)

    

此时文字内容移动到右下角。此时我们应该可以理解,为什么上面例子中调用scrollBy(),y方向偏移量输入负值,文字内容却往下移动,因为这个偏移量作用的是与View边框左上角对齐的座标。y方向对齐的座标减少,需将画布下移,所以文字内容下移。同样的,scrollTo()参数传入座标指的是与View边框左上角对齐的画布座标。

最后总结一下:

1.scrollTo() / scrollBy() 移动的是View的内容(画布)。

2.scrollTo()的参数座标指的是与View边框左上角对齐的画布座标,scrollBy()参数的偏移量作用于与View边框左上角的画布座标。

3.ViewGroup调用时这两个方法移动的是所有子View

4.getScrollX()和getScrollY()得到的是当前与View边框左上角对齐的画布座标值。(因为一开始为(0,0),移动后的值减(0,0)即为移动后的座标值)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章