我有一个从服务器加载数据的回收视图。它有一个GridLayout
作为它的layoutmanager
。在屏幕方向上,我想保留回收视图
的滚动位置。我尝试了堆栈溢出的许多解决方案。但它并不完美。我的意思是“不完美地工作”,它在多次屏幕方向后没有保留正确的滚动位置。这是我的代码实现:
onSaveInstanceState
和onRestoreInstanceState
:
@Override
protected void onSaveInstanceState(Bundle outState) {
listState = recyclerView.getLayoutManager().onSaveInstanceState();
outState.putParcelable(Constants.POSITION, listState);
super.onSaveInstanceState(outState);
}
protected void onRestoreInstanceState(Bundle state) {
// Retrieve list state and list/item positions
if (state != null) {
listState = state.getParcelable(Constants.POSITION);
Log.e(TAG, "list state not null");
}
super.onRestoreInstanceState(state);
}
private void restoreState() {
Log.e(TAG, "restoreStated called");
if (listState != null) {
recyclerView.getLayoutManager().onRestoreInstanceState(listState);
listState = null;
}
}
设置数据后调用恢复状态:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
((MyApplication) getApplication()).getComponent().inject(this);
movieListViewModel = ViewModelProviders.of(this).get(MovieListViewModel.class);
recyclerView.setHasFixedSize(true);
gridLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(gridLayoutManager);
adapter = new MovieListAdapter(MainActivity.this);
recyclerView.setAdapter(adapter);
movieListViewModel.getMovieList();
observePopularMovieList();
}
private void observePopularMovieList() {
movieListViewModel.result.observe(this, new Observer<NetworkResponse>() {
@Override
public void onChanged(@Nullable NetworkResponse networkResponse) {
if (networkResponse.getPostData() != null) {
movieData = networkResponse.getPostData();
adapter.addData(movieData.getResults());
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
restoreState();
}
},50);
} else {
Log.e(TAG, "failure");
}
}
});
}
如果您在活动中有回收器视图,请尝试将回收器ViewAdapter保存在活动的ViewModel中,并在方向更改时获取适配器并将其设置为回收器视图。
如果你在一个片段中有回收视图,那么尝试在方向改变时获得相同的片段
片段保存片段=getSupportFragmentManager(). findFragmentByTag("Fragment_having_recyclerview");
然后设置这个片段,而不是创建同一个片段的新实例
您应该使用savedInstanceBundle而不是将其保存在某个变量中,因为当屏幕方向发生变化时,活动将被销毁并重新创建,因此您的所有活动状态都将被销毁并重新创建。
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("pos", mRecyclerView.getAdapterPosition()); // gives current recycle view position.
super.onSaveInstanceState(savedInstanceState);
}
然后在onCreate()
中可以得到这样的位置。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
..
..
mRecyclerView.setAdapter(mRecyclerAdapter);
if(savedInstanceState != null){
mRecyclerView.post(new Runnable() {
@Override
public void run() {
int pos = savedInstanceState.getInt("pos");
mRecyclerView.scrollToPosition(pos);
}
});
}
}
在Adapter类中创建getAdapterPopse()
,如下所示。
private class ComponentRecycleAdapter extends RecyclerView.Adapter<ComponentHolder> {
ComponentHoder myHolder = null;
@Override
public ComponentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.one_component_item_list, parent, false);
return new ComponentHolder(view);
}
@Override
public void onBindViewHolder(ComponentHolder holder, int position) {
..
..
..
this.myHolder = holder;
}
@Override
public int getItemCount() {
..
}
public int getAdapterPosition(){
return myHolder =! null ? myHolder.getAdapterPosition() : 0;
}
}
让我知道它是否有效。快乐编码:)
在尝试了很多解决方案后,这帮助我准确地恢复了回收视图的位置
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == SCREEN_ORIENTATION_LANDSCAPE || newConfig.orientation == SCREEN_ORIENTATION_USER) {
if(mRecyclerView!=null && mRecyclerView.getLayoutManager()!=null) {
mBundleRecyclerViewState = new Bundle();
mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
}
} else if (newConfig.orientation == SCREEN_ORIENTATION_PORTRAIT) {
if (mBundleRecyclerViewState != null) {
new Handler().postDelayed(() -> {
if(mRecyclerView!=null && mRecyclerView.getLayoutManager()!=null) {
mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
}
}, 100);
}
}
}