【问题标题】:Can't restore scroll position after rotation (RecyclerView)旋转后无法恢复滚动位置(RecyclerView)
【发布时间】:2017-04-30 07:39:18
【问题描述】:

旋转后以及关闭应用程序并再次打开后,无法恢复 RecyclerView 的滚动位置。在第一种情况下,我可以在 Manifest 中使用 android:configChanges,但在我重新打开应用程序后它没有帮助。 这是我的代码。尝试恢复状态后,我看到一个没有我的列表的空白屏幕。

public class MainActivity extends AppCompatActivity implements IMainContract.View {

    private final String BUNDLE_RECYCLER_LAYOUT = MainActivity.class.getSimpleName() + ".save.state.list";

    private IMainContract.Presenter mainPresenter;
    private MainAdapter adapter;
    private LinearLayoutManager layoutManager;

    private ImageView ivRefresh;
    private ProgressBar progressBar;
    private RecyclerView rvUsers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ivRefresh = (ImageView) findViewById(R.id.ivRefresh);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        rvUsers = (RecyclerView) findViewById(R.id.rvUsers);

        layoutManager = new LinearLayoutManager(this);
        rvUsers.setLayoutManager(layoutManager);

        mainPresenter = new MainPresenter(Repository.getInstance(this), this);

        adapter = new MainAdapter(new ArrayList<>(), this);
        rvUsers.setAdapter(adapter);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ivRefresh.setOnClickListener(v -> mainPresenter.onRefreshPressed());

        if (savedInstanceState != null) {
            Parcelable savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
            layoutManager.onRestoreInstanceState(savedRecyclerLayoutState);
        } else {
            mainPresenter.subscribe();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, layoutManager.onSaveInstanceState());
    }
//...

}

【问题讨论】:

标签: android android-recyclerview screen-rotation


【解决方案1】:

您需要在 stackoverflow 上关注此answer。更改您的代码

public class MainActivity extends AppCompatActivity { 


    private final String KEY_RECYCLER_STATE = "recycler_state";

    private MainAdapter adapter;
    private LinearLayoutManager layoutManager;

    private ImageView ivRefresh;
    private ProgressBar progressBar;
    private RecyclerView rvUsers;
    private static Bundle mBundleRecyclerViewState;

    @Override 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ivRefresh = (ImageView) findViewById(R.id.ivRefresh);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        rvUsers = (RecyclerView) findViewById(R.id.rvUsers);

        layoutManager = new LinearLayoutManager(this);
        rvUsers.setLayoutManager(layoutManager);


        adapter = new MainAdapter(new ArrayList<>(), this);
        rvUsers.setAdapter(adapter);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);




    } 


    @Override 
    protected void onPause() 
    { 
        super.onPause(); 

        // save RecyclerView state 
        mBundleRecyclerViewState = new Bundle();
        Parcelable listState = rvUsers.getLayoutManager().onSaveInstanceState();
        mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, listState);
    } 

      @Override 
    protected void onResume() 
    { 
        super.onResume(); 

        // restore RecyclerView state 
        if (mBundleRecyclerViewState != null) {
            Parcelable listState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
            rvUsers.getLayoutManager().onRestoreInstanceState(listState);
        } 
    } 


} 

【讨论】:

  • 有了这段代码,旋转后我的屏幕也是空的
【解决方案2】:

您需要覆盖onRestoreInstanceState() 并使用保存的bundle 设置recyclerView.getLayoutManager()

Parcelable savedRecyclerLayoutState ;

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

        if(savedInstanceState != null)
        {
            savedRecyclerLayoutState = savedInstanceState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
            rvUsers.getLayoutManager().onRestoreInstanceState(savedRecyclerLayoutState);
        }
    }

您还需要在您的活动中覆盖onResume()

 @Override
protected void onResume() {
    super.onResume();

    if (savedRecyclerLayoutState != null) {
        layoutManager.onRestoreInstanceState(savedRecyclerLayoutState );
    }
}

【讨论】:

  • 结果一样:旋转后我的屏幕是空的。
  • @alla 如果旋转后屏幕为空,那是因为您没有保存/恢复RecyclerView 的内容。与滚动位置的保存/恢复不同。
  • @Sufian 你是对的,谢谢。我也必须保存我的清单。现在可以了
  • @Sufian 你不想写答案吗?我会接受的。
  • @alla 不幸的是,这里的社区鼓励将重复的问题标记为重复。
【解决方案3】:

最初你必须通过调用来获取 RecyclerView 的当前滚动位置:

int index = rvUsers.getFirstVisiblePosition();

然后你必须在方向改变时保存这个值,当 RecyclerView 再次创建时你必须将你的 RecyclerView 移动到这个索引。

我想这可行:

rvUsers.smoothScrollToPosition(int index)

如果您使用的是旧版本 使用

setSelection(int position)

和

getFirstVisiblePosition() 

方法

【讨论】:

    【解决方案4】:

    您可以将位置存储在共享偏好中,当您重新启动应用程序时,您可以从首选项中获取值并相应地填充回收器视图

    【讨论】:

    • 1.将滚动位置存储在活动/片段的 onpause/ondestroy 中的 sharedpreferences 中。 2.在onResume中恢复滚动位置。获取滚动位置的方法的其他答案
    • 这并没有提供问题的答案。一旦您有足够的声誉,您就可以对任何帖子发表评论;相反,提供不需要提问者澄清的答案
    【解决方案5】:

    使用已填充的数据设置适配器很重要。在这种情况下,位置会自动恢复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 2020-11-08
      相关资源
      最近更新 更多