简体   繁体   English

无法使用LayoutManager在RecyclerView中还原滚动位置

[英]Unable to Restore the Scroll Position in RecyclerView using LayoutManager

So, I have an EditText on which I have set onEditorActionListener, ie after the user enters the text and presses enter/search it will fetch the details and populate the recycler view accordingly. 因此,我有一个EditText,在其上设置了onEditorActionListener,即,在用户输入文本并按Enter / Search后,它将获取详细信息并相应地填充回收者视图。

Now in order to save the state on a configuration change I have wrote the following code - 现在,为了保存配置更改的状态,我编写了以下代码-

Parcelable stateList;

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    //Saving instance of the state in Parcelable stateList
    stateList = recyclerView.getLayoutManager().onSaveInstanceState();
    outState.putParcelable(RETAIN_STATE, stateList);
}

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

    if(savedInstanceState!=null) {
        stateList = savedInstanceState.getParcelable(RETAIN_STATE);
        recyclerView.getLayoutManager().onRestoreInstanceState(stateList);
    }
}

But when I run this, and rotate the screen the recycler view does not restore the state from the stateList parcelable. 但是,当我运行它并旋转屏幕时,回收者视图不会从可拆分的stateList中恢复状态。

I am using MVP, so I'm setting the adapter in the callback of the presenter. 我正在使用MVP,因此在演示者的回调中设置适配器。

I was able to retain the state when we click on enter/search on the keyboard after the screen was rotated, so I tried this hack in the onRestoreInstanceState(), but I think there should be a better way to go about this. 旋转屏幕后,当我们单击键盘上的enter / search时,我能够保留状态,因此我在onRestoreInstanceState()中尝试了此技巧,但我认为应该有更好的方法来解决此问题。

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

    if(savedInstanceState!=null) {
        //The hack!
        et_search.onEditorAction(EditorInfo.IME_ACTION_SEARCH);
        stateList = savedInstanceState.getParcelable(RETAIN_STATE);
        recyclerView.getLayoutManager().onRestoreInstanceState(stateList);
    }
}

Let me know if there is more information needed. 让我知道是否需要更多信息。 Thanks in advance. 提前致谢。

You don't really need to call onRestoreInstanceState on configuration change in LayoutManager because it'll be called automatically (all views have onSaveInstanceState and onRestoreInstanceState that's passed from life-cycle owner). 您实际上不需要在LayoutManager中进行配置更改时调用onRestoreInstanceState ,因为它将被自动调用(所有视图都具有从生命周期所有者传递的onSaveInstanceStateonRestoreInstanceState )。 Even if you want to - all you'll achieve with this is restore scroll position of views. 即使您愿意-所要做的就是恢复视图的滚动位置。

What you actually need to do is save data set/used in RecyclerView adapter and set it back when screen is rotated. 您实际需要做的是保存在RecyclerView适配器中设置/使用的数据,并在旋转屏幕时将其重新设置。 And then call search(or filter, whatever) again. 然后再次调用搜索(或过滤器,无论如何)。

You can let android handle the orientation changes for you if don't want to any custom stuff by overriding config change.eg hiding some view etc 如果您不想通过覆盖配置更改来定制任何东西,可以让android为您处理方向更改。例如,隐藏一些视图等

<activity android:name=".mainpage.view.MainActivity" android:configChanges="orientation|screenSize|screenLayout" >

Include this in your manifest for that activity Further to save scroll position in recyler view on rotation you can use following gist to avoid duplicate code as you can use this custom recyclerview in your project wherever same feature required 将此内容包含在该活动的清单中,进一步在旋转时在recyler视图中保存滚动位置,您可以使用以下要点来避免重复代码,因为可以在需要相同功能的项目中使用此自定义recyclerview

 import android.content.Context; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; /** * Class {@link StatefulRecyclerView} extends {@link RecyclerView} and adds position management on configuration changes. * * @author FrantisekGazo * @version 2016-03-15 */ public final class StatefulRecyclerView extends RecyclerView { private static final String SAVED_SUPER_STATE = "super-state"; private static final String SAVED_LAYOUT_MANAGER = "layout-manager-state"; private Parcelable mLayoutManagerSavedState; public StatefulRecyclerView(Context context) { super(context); } public StatefulRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public StatefulRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(SAVED_SUPER_STATE, super.onSaveInstanceState()); bundle.putParcelable(SAVED_LAYOUT_MANAGER, this.getLayoutManager().onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; mLayoutManagerSavedState = bundle.getParcelable(SAVED_LAYOUT_MANAGER); state = bundle.getParcelable(SAVED_SUPER_STATE); } super.onRestoreInstanceState(state); } /** * Restores scroll position after configuration change. * <p> * <b>NOTE:</b> Must be called after adapter has been set. */ private void restorePosition() { if (mLayoutManagerSavedState != null) { this.getLayoutManager().onRestoreInstanceState(mLayoutManagerSavedState); mLayoutManagerSavedState = null; } } @Override public void setAdapter(Adapter adapter) { super.setAdapter(adapter); restorePosition(); } } 

Link to gist 链接到要点

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM