更好地理解 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)即爲移動後的座標值)

 

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