开发者

ScrollView .scrollTo not working? Saving ScrollView position on rotation

Ok.. I must be overlooking something real simple here, but i think i'm trying to do something fairly basic.. Simply retain the scrollbar position of a ScrollView on orientation change...

Here is the code for my onSaveInstanceState and onRestoreInstanceState.. sView is the container for the ScrollView layout. Within my scrollview is a linearlayout with a lot of textviews.

    @Override 
public void onSaveInstanceState(Bundle outState) 
{
    //---save whatever you need to persist—

    outState.putInt("sViewX",sView.getScrollX());
    outState.putInt("sViewY",sView.getScrollY());

super.onSaveInstanceState(outState);

}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) 
{
    super.onRestoreInstanceState(savedInstanceState);

    sViewX = savedInstanceState.getInt("sViewX");   
    sViewY = savedInstanceState.getInt("sViewY");

    sView.scrollTo(sViewX, sViewY);

}

If I set a Toast with the values of sViewX and sViewY on the Restore, the values are kept and correct.

Edit: I just tried to do a sView.s开发者_运维知识库crollTo(0,150); in my onCreate.. just to see if that would open the activity at 150px down, and it didn't. I think my issue has to do with the .scrollTo method.


I figured it out.

Since I'm using setText to TextViews in my onCreate, calling .scrollTo won't work.

So now I'm using the following:

sView.post(new Runnable() {
    @Override
    public void run() {
        sView.scrollTo(sViewX, sViewY);
    } 
});


onRestoreInstanceState() is just to early to scroll the view. That's why posting new Runnable helps, but not always. Sometimes one even have to use postDelayed() to let it work. For Fragment one can use onViewCreated() instead :

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    sViewX = savedInstanceState.getInt("sViewX");   
    sViewY = savedInstanceState.getInt("sViewY");
    sView.scrollTo(sViewX, sViewY);
}


This is working for me

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt(SystemGlobal.SCROLL_Y, mRelativeLayoutMain.getTop());
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onRestoreInstanceState(savedInstanceState);
    mRelativeLayoutMain.scrollTo(0, savedInstanceState.getInt(SystemGlobal.SCROLL_Y));
}


You should start scroll before components are drawn, since scroll does not work untill components are not created:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    scrollView.scrollTo(.... 


this code worked for me for dynamically scrolling tabs, maybe it will be useful for u

TabHost tabHost;
int currentActiveTab;
HorizontalScrollView tabsHorizontalScrollView;
//some code ...
tabHost = getTabHost();
tabsHorizontalScrollView = findViewById(R.id.tabsHorizontalScrollView);
currentActiveTab = 8;
//some code ...
tabHost.setCurrentTab(currentActiveTab);
tabHost.getTabWidget().getChildAt(currentActiveTab).post(new Runnable() {
  @Override
  public void run() {
    tabsHorizontalScrollView.scrollTo(tabHost.getTabWidget().getChildAt(currentActiveTab).getLeft(), tabsHorizontalScrollView.getScrollY());
  }
});


For MVVMCross:

protected override void OnSaveInstanceState(Bundle outState)
{
    base.OnSaveInstanceState(outState);

    ScrollView sv = FindViewById<ScrollView>(Resource.Id.dispatchScrollView);
    int posY = sv.ScrollY;

    outState.PutInt("scrollY", posY);
}

protected override void OnRestoreInstanceState(Bundle savedInstanceState)
{
    base.OnRestoreInstanceState(savedInstanceState);

    ScrollView sv = FindViewById<ScrollView>(Resource.Id.dispatchScrollView);
    int posY = savedInstanceState.GetInt("scrollY");

    sv.Post(new Runnable(new Action(() => sv.ScrollTo(0, posY))));
}


Instead of sending scroll action to next run-loop, you can scroll your view in global layout callback:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    sView.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                sView.scrollTo(sViewX, sViewY);
            }
        }
    );
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜