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)即爲移動後的座標值)