【问题标题】:Save the position of scrollview when the orientation changes当方向改变时保存滚动视图的位置
【发布时间】:2015-03-23 10:35:22
【问题描述】:

这是我的布局:

当方向改变时,我需要保存滚动位置。例如,如果屏幕在纵向模式下显示从中间名开始的布局,则在横向模式下应该从中间名开始。

【问题讨论】:

    标签: android android-layout orientation


    【解决方案1】:

    只需在滚动元素上设置 android:id。您的视图将自动保存其滚动位置。

    来自 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);
            }
        }
    }
    

    【讨论】:

    • 很好的答案!我认为这是滚动视图不恢复其位置的最常见原因
    • 这应该被标记为正确答案。尽管从 View.java 发布代码在这种情况下有点令人困惑。
    • 当我在NestedScrollView 中有一个RecyclerView 时,这对我不起作用,但下面 Umesh Clauhan 的解决方案有效。
    • 哇!令人兴奋的解决方案,如果您要恢复视图状态,这只会起作用。但这肯定不是解决方案,因为必须重新创建视图并向用户显示,就像什么都没发生一样。
    【解决方案2】:

    要在手机方向改变时保存和恢复 ScrollView 的滚动位置,您可以执行以下操作: 在 onSaveInstanceState 方法中保存当前位置:

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

    然后在 onRestoreInstanceState 方法中恢复位置。请注意,我们需要将 Runnable 发布到 ScrollView 以使其工作:

    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]);
                }
            });
    }
    

    在谷歌上找到了这个解决方案。归功于原始编码器。 :)

    【讨论】:

    • 你拯救了我的一天!
    • 这不是必须的,您只需要在 ScrollView 上设置一个 ID(查看实际答案...)
    • 尝试添加此偏移量以获得从垂直方向更改为水平方向时的确切位置:mScrollView.scrollTo(position[0], position[1] + getScreenWidth()/4);
    【解决方案3】:

    在我的三星平板电脑上,我不必添加太多代码(只需调用超类)。另外,我在 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>
    

    【讨论】:

      【解决方案4】:

      【讨论】:

      • 不要只发布链接答案。链接中的内容可能会更改或链接可能会停止工作。而是在您的答案中包含相关内容,并提供归因或进一步阅读的链接
      【解决方案5】:

      在清单中执行此操作..

        <activity
              android:name=".YourActivity"
              android:configChanges="keyboardHidden|orientation|screenSize"
              android:label="@string/app_name" >
        </activity>
      

      【讨论】:

        【解决方案6】:

        您如果您的活动在轮换中没有改变任何内容,您可以使用 android:configChanges="orientation|keyboardHidden|screenSize" 在此特定活动的清单文件中。但这显然是解决方法,而不是适当的解决方案。

        注意:

        如果您需要为横向和纵向使用不同的视图,或者如果您需要为不同的设备使用不同的视图,则应该使用 bundle 并在 onsaveinstancestate 中保存数据并在 oncreate 中检索数据。此方法停止重新创建活动,活动假定事情将由用户自己处理。

        【讨论】:

        • 如果您有不同的横向和纵向视图,这不是一个好的解决方案,因为 Activity 和 Fragment 都不会使用此配置重新创建其视图。您可能还会得到一个看起来很奇怪的操作栏。
        • 是的,约翰,同意并相应地修改了答案。
        • 您不应该依赖配置更改。看到这个:stackoverflow.com/a/7990543/3113823
        • 这只是一种解决方法,它不是正确的解决方案。
        • 笔记里也写了兄弟
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多