21

These is my layout:

detail layout

I need to save the scrolling position when the orientation changes. for example if the screen shows layout starting from middle name in portrait mode,it should start from same in the landscape mode.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440

6 Answers6

66

Just set android:id on your scrolling element. Your view will save its scrolling position automatically.

Code from View.java:15554

protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
    if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
        mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
        Parcelable state = onSaveInstanceState();
        if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
            throw new IllegalStateException(
                    "Derived class did not call super.onSaveInstanceState()");
        }
        if (state != null) {
            // Log.i("View", "Freezing #" + Integer.toHexString(mID)
            // + ": " + state);
            container.put(mID, state);
        }
    }
}
Nicola Gallazzi
  • 7,897
  • 6
  • 45
  • 64
  • 2
    Great answer! I think this is the most common reason why scrollviews dont restore their position – athor Nov 04 '16 at 00:23
  • 7
    This should be marked as correct answer. Although posting code from View.java is a little confusing in this context. – Greg Ennis Jun 27 '17 at 03:04
  • 2
    This did not work for me when having a `RecyclerView` inside a `NestedScrollView` but the solution of Umesh Clauhan below worked. – Minas Mina Sep 06 '17 at 14:01
  • Wow! mindblowing solution and this just works if you are restoring the view state. But this certainly is not a solution when, views have to be recreated and shown to the user like nothing happened. – sud007 Feb 28 '20 at 19:58
44

To save and restore the scroll position of a ScrollView when the phone orientation changes you can do the following: Save the current position in the onSaveInstanceState method:

protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putIntArray("ARTICLE_SCROLL_POSITION",
            new int[]{ mScrollView.getScrollX(), mScrollView.getScrollY()});
}

Then restore the position in the onRestoreInstanceState method. Note that we need to post a Runnable to the ScrollView to get this to work:

protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    final int[] position = savedInstanceState.getIntArray("ARTICLE_SCROLL_POSITION");
    if(position != null)
        mScrollView.post(new Runnable() {
            public void run() {
                mScrollView.scrollTo(position[0], position[1]);
            }
        });
}

Found this solution on google. Credit goes to Original Coder. :)

Umesh Chauhan
  • 1,460
  • 1
  • 17
  • 26
0

On my Samsung tablet, I didn't have to add as much code (just the call to the superclass). Also, I already had a name on the ListView.

protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/search_text"
        android:maxLines="1"
        android:inputType="text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Enter search string here" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="doSearch"
        android:clickable="true"
        android:text="Search"
        android:layout_toRightOf="@id/search_text"/>

    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/list_of_books"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/search_text"
        android:divider="@null"
        android:orientation="vertical" />

</RelativeLayout>
Ed Poor
  • 1,849
  • 20
  • 13
-1

refer these to persist the scroll position and scroll after orientation change.

https://asishinwp.wordpress.com/2013/04/15/save-scrollview-position-resume-scrollview-from-that-position/

https://eliasbland.wordpress.com/2011/07/28/how-to-save-the-position-of-a-scrollview-when-the-orientation-changes-in-android/

Dinesh Kannan
  • 1,255
  • 13
  • 32
  • Don't post link only answers. The content in the links may change or the link may stop working. Instead include the relevant content in your answer and provide links for attribution or further reading – TheIT Feb 15 '17 at 22:27
-5

Do this in manifest..

  <activity
        android:name=".YourActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:label="@string/app_name" >
  </activity>
Sjd
  • 1,261
  • 1
  • 12
  • 11
-15

You If your activity is not changing anything on rotation you can use android:configChanges="orientation|keyboardHidden|screenSize" in manifest file within this particular activity. But this is clearly workaround and not a proper solution.

Note:

If you need to use different views for landscape and portraits or if you need to use different views for different devices, One should use bundle and save data onsaveinstancestate and retrieve the data in oncreate. This method stops to recreate the activity and activity assumes that things will be handled by the user himself/herself.

MrDumb
  • 2,140
  • 1
  • 21
  • 31