1

I've got such a layout:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ScrollView
        android:id="@+id/scroll_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:fillViewport="true" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            ... 
            other views 
            ... 

            <TextView
                android:id="@+id/text_view_that_can_change"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </RelativeLayout>
    </ScrollView>

    <include
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        layout="@layout/btns_ok_cancel" />

</RelativeLayout>

The problem is that when I add text to initially empty text_view_that_can_change - my ScrollView scrolls to the top.
The same problem happens when I set visibility to some of views inside ScrollView/RelativeLayout.

I can scroll it back using scrollView.scrollTo(0, yScroll) but it gives a visible and, I must say, ugly jerk to the whole content.

It there any way to prevent this behavior?

sberezin
  • 3,266
  • 23
  • 28
  • My guess would be to stop Android's default focus behavior, try [this](http://stackoverflow.com/a/7376538/1440950) – Ertyguy Jan 25 '15 at 22:11
  • Thanks for your comment, but it looks it's connected to re-laying out, not to focus – sberezin Jan 26 '15 at 12:55

1 Answers1

0

Have spent some hours and here is what I've discovered.

Scroll to the top happens because inner RelativeLayout is being re-laid out as a result of the content change.

You should add a couple of lines to control this situation:
1) declare class member that will hold scroll position:

int mSavedYScroll;

2) Add GlobalLayoutListener to the main view (here it's a fragment's main view, but that doesn't matter):

    public View onCreateView(...) {
        mView = inflater.inflate(...);
        ...

        mView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (mSavedYScroll != 0) {
                    mScrollContainer.scrollTo(0, mSavedYScroll);
                    mSavedYScroll = 0;
                }
            }
        });
}

3) When you do something (anywhere in you code) that may change content of ScrollView - just save current scroll position:

     mSavedYScroll = mScrollContainer.getScrollY();
     //DO SOMETHING THAT MAY CHANGE CONTENT OF mScrollContainer:
     ...

That's it!

sberezin
  • 3,266
  • 23
  • 28