【问题标题】:Maintaining list items positions on device rotation in an android fragment在android片段中维护设备旋转的列表项位置
【发布时间】:2017-07-04 23:00:08
【问题描述】:

在一个片段中,我试图保存 RecyclerView 列表的滚动状态,但不知何故它没有保存状态。因为它是一个片段,所以我重写了 onSaveInstanceState() 和 onActivityCreated() 方法来保存滚动位置。甚至尝试在 onViewStateRestored() 方法中实现。我看到一些有关保存滚动状态的帖子,但它不起作用。请让我知道我在哪里失败。以下是我的代码:

public class RecipeListFragment extends Fragment
    implements RecipeListContract.View {
@BindView(R.id.recipe_list_recycler_view)
RecyclerView mRecipeListRecyclerView;
@BindView(R.id.recipe_list_progress_bar)
ProgressBar mRecipeListProgressBar;

@BindInt(R.integer.grid_column_count)
int mGridColumnCount;
@BindString(R.string.recipe_list_sync_completed)
String mRecipeListSyncCompleted;
@BindString(R.string.recipe_list_connection_error)
String mRecipeListConnectionError;

GridLayoutManager gridLayoutManager;
Parcelable savedRecyclerLayoutState;

Unbinder unbinder;

private static final String SAVED_LAYOUT_MANAGER
        = "com.learnwithme.buildapps.bakingapp.ui.recipelist.fragment";

private RecipeListContract.Presenter mRecipeListPresenter;
private RecipeListAdapter mRecipeListAdapter;

public RecipeListFragment() { }

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup 
container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_recipe_list, container, 
false);
unbinder = ButterKnife.bind(this, view);

mRecipeListAdapter = new RecipeListAdapter(
            getContext(),
            new ArrayList<>(0),
            recipeId -> mRecipeListPresenter.loadRecipeDetails(recipeId)
);
mRecipeListAdapter.setHasStableIds(true);

    gridLayoutManager = new GridLayoutManager(getContext(), 
mGridColumnCount);
    mRecipeListRecyclerView.setLayoutManager(gridLayoutManager);
    mRecipeListRecyclerView.setHasFixedSize(true);
    mRecipeListRecyclerView.setAdapter(mRecipeListAdapter);

    return view;
}

@Override
public void onPause() {
    super.onPause();
    mRecipeListPresenter.unsubscribe();
}

@Override
public void onResume() {
    super.onResume();
    mRecipeListPresenter.subscribe();
}

@Override
public void onSaveInstanceState() { }

@Override
public void onSaveInstanceState(Bundle bundle) {
    super.onSaveInstanceState(bundle);
    if(bundle != null) {
        bundle.putParcelable(SAVED_LAYOUT_MANAGER,
                mRecipeListRecyclerView
                    .getLayoutManager()
                    .onSaveInstanceState());
        Timber.d("instance state=>", 
mRecipeListRecyclerView.getLayoutManager().onSaveInstanceState());
    }
}

@Override
public void onViewStateRestored(@Nullable Bundle bundle) {
    super.onViewStateRestored(bundle);
    if(bundle != null) {
        savedRecyclerLayoutState = 
bundle.getParcelable(SAVED_LAYOUT_MANAGER);
        Timber.d("onViewStateRestored savedRecyclerLayoutState=>", 
savedRecyclerLayoutState);
        mRecipeListRecyclerView
                .getLayoutManager()
                .onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onActivityCreated(@Nullable Bundle bundle) {
    super.onActivityCreated(bundle);
    if(bundle != null) {
        savedRecyclerLayoutState = 
bundle.getParcelable(SAVED_LAYOUT_MANAGER);
        Timber.d("onViewStateRestored savedRecyclerLayoutState=>",
                savedRecyclerLayoutState);
        mRecipeListRecyclerView
                .getLayoutManager()
                .onRestoreInstanceState(savedRecyclerLayoutState);
    }
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
}

public static RecipeListFragment newInstance() {
    return new RecipeListFragment();
}

@Override
public void setPresenter(RecipeListContract.Presenter recipeListPresenter) {
    this.mRecipeListPresenter = recipeListPresenter;
}

@Override
public void showRecipeList(List<Recipe> recipeList) {
    mRecipeListAdapter.refreshRecipes(recipeList);
}

@Override
public void loadProgressBar(boolean show) {
    setViewVisibility(mRecipeListRecyclerView, !show);
    setViewVisibility(mRecipeListProgressBar, show);
}

@Override
public void displayCompletedMessage() {
    Toast.makeText(getContext(), mRecipeListSyncCompleted, 
Toast.LENGTH_SHORT).show();
}

@Override
public void displayErrorMessage() {
    Toast.makeText(getContext(), mRecipeListConnectionError, 
Toast.LENGTH_SHORT).show();
}

@Override
public void displayRecipeDetails(int recipeId) {
    startActivity(RecipeDetailsActivity.prepareIntent(getContext(), 
recipeId));
}

private void setViewVisibility(View view, boolean visible) {
    if (visible) {
        view.setVisibility(View.VISIBLE);
    } else {
        view.setVisibility(View.INVISIBLE);
    }
}
}

【问题讨论】:

    标签: android android-fragments android-recyclerview android-fragmentactivity


    【解决方案1】:

    我自己解决了这个问题。问题是在 onSaveInstanceState() 中保存设备的滚动位置并在 onViewRestored() 方法中恢复相同的位置。

    private Parcelable mRecipeListParcelable;
    private int mScrollPosition = -1;
    
    @Override
    public void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
        int scrollPosition = ((GridLayoutManager) 
        mRecipeListRecyclerView.getLayoutManager())
                .findFirstCompletelyVisibleItemPosition();
        mRecipeListParcelable = gridLayoutManager.onSaveInstanceState();
        bundle.putParcelable(KEY_LAYOUT, mRecipeListParcelable);
        bundle.putInt(POSITION, scrollPosition);
    }
    
    @Override
    public void onViewStateRestored(@Nullable Bundle bundle) {
        super.onViewStateRestored(bundle);
        if(bundle != null) {
            mRecipeListParcelable = bundle.getParcelable(KEY_LAYOUT);
            mScrollPosition = bundle.getInt(POSITION);
        }
    }
    

    另外,在 loadProgress() 方法中,我必须设置 scrollToPosition() 并保存滚动位置。

    @Override
    public void loadProgressBar(boolean show) {
        setViewVisibility(mRecipeListRecyclerView, !show);
        setViewVisibility(mRecipeListProgressBar, show);
        mRecipeListRecyclerView.scrollToPosition(mScrollPosition);
    }
    

    另外,要记住的另一件事是无需在 onResume() 方法中恢复任何内容,因为会调用演示者回调并且无论如何都会重置视图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多