當我在使用scollview時發現一個有趣的現象,在按鈕點選的事件中,我們進行對與scollview的位置設定scollTo方法是完全ok的,但是當我們想要在初始化過程中就進行對scollview滑動到的位置進行設定時,就無效了。
網上找了一些資料,都說是用handler.postDelayed方法,進行一個延遲操作,試過了之後,并沒有什麼用,
由此對scollview進行研究:
1.scrollTo() 是直接指定滾動條的位置, 但是由于這個動作不是單純關于 ScrollView 而已, 還要根據 ScrollView 裡面包含的View 的實際資訊. 是以這動作必須在頁面加載完成以後才能執行.
2 那麼如何判斷頁面加載完成呢,在activity中有這樣一個方法:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
//do something 當activity 得到或者失去焦點時,會執行的方法,得到焦點傳回 true,反之
}
}
3.activity中頁面初始化渲染完成之後,進行scollview位置的設定:
mScrollView.post(new Runnable() {
@Override
public void run() {
mScrollView.scrollTo(, ); // 0 代表x軸移動的距離, 1000表示y軸移動的距離
}
});
4下面進行源碼剖析:
scollview源碼:
/**
* {@inheritDoc}
*
* <p>This version also clamps the scrolling to the bounds of our child.
*/
@Override
public void scrollTo(int x, int y) {
// we rely on the fact the View.scrollBy calls scrollTo.
if (getChildCount() > ) {
View child = getChildAt();
x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
if (x != mScrollX || y != mScrollY) {
super.scrollTo(x, y);
}
}
}
它的父類View:
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
invalidate();
}
}
}
由此可見:
if (mScrollX != x || mScrollY != y) 這個判斷語句有沒有通過是關鍵所在. 這也間接說明了, 在Activity 沒初始化完成, ScrollView 對象擷取的一些資訊是不準确的, 直接導緻了scrollTo() 方法無效.
5.于是我們得出結論,要想在初始化中設定horizontalscollview的位置,需要在activity頁面渲染完成之後,進行設定,也就是在onWindowFocusChanged 方法中設定偏移位置,則生效。