Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/205.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在RecyclerView中保留ViewPager状态?_Android_Android Viewpager_Android Recyclerview - Fatal编程技术网

Android 如何在RecyclerView中保留ViewPager状态?

Android 如何在RecyclerView中保留ViewPager状态?,android,android-viewpager,android-recyclerview,Android,Android Viewpager,Android Recyclerview,我的RecyclerView包含许多ViewPager。每个ViewPager内的页数是恒定的(2)。我用PagerAdapter 当我滚动我的RecyclerView时,ViewPagers将失去其状态并重置为第一页。我想知道如何为每个ViewPager保留最后选定的页面 例如: 1) 我在第一个ViewPager中滚动到第2页 2) 我将RecyclerView滚动到底部,我的第一个ViewPager将退出屏幕。 3) 我滚动到ViewPager的顶部,因此我的第一个ViewPager将再次

我的RecyclerView包含许多ViewPager。每个ViewPager内的页数是恒定的(2)。我用PagerAdapter

当我滚动我的RecyclerView时,ViewPagers将失去其状态并重置为第一页。我想知道如何为每个ViewPager保留最后选定的页面

例如: 1) 我在第一个ViewPager中滚动到第2页 2) 我将RecyclerView滚动到底部,我的第一个ViewPager将退出屏幕。 3) 我滚动到ViewPager的顶部,因此我的第一个ViewPager将再次加载。 4) 我的第一个ViewPager设置为第1页,而不是我最后滚动到的第2页

在RecyclerView中有“n”个ViewPager,我希望保留它们的所有状态,而不管是否由于RecyclerView而重新加载


如何解决这个逻辑?

好吧,我为此写了一点蛮力解决方案

My
PagerAdapter

public class ViewPagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        FrameLayout layout = new FrameLayout(container.getContext());
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        layout.setLayoutParams(layoutParams);

        layout.setBackgroundColor(position % 2 == 0 ? Color.RED : Color.BLUE);
        container.addView(layout);
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}
(因此,我们认为视觉上的“状态”在颜色上是不同的——第一个位置是红色,第二个位置是蓝色)

RecycleServiceAdapter
看起来像:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public HashMap<Integer, Integer> viewPageStates = new HashMap<>();

    public RecyclerViewAdapter() {}

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        return new ViewHolder(new ViewWithViewPager(viewGroup.getContext()));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((ViewWithViewPager) holder.itemView).refreshState(position, viewPageStates.containsKey(position)? viewPageStates.get(position) : 0);
    }

    @Override
    public int getItemCount() {
        return 42;
    }

    @Override
    public void onViewRecycled(RecyclerView.ViewHolder holder) {
        ViewWithViewPager recycledViewPager = ((ViewWithViewPager)holder.itemView);
        viewPageStates.put(recycledViewPager.viewPosition, recycledViewPager.viewPager.getCurrentItem());
        super.onViewRecycled(holder);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public ViewHolder(View itemView) {
            super(itemView);
        }
    }
}   
也就是说,在
刷新状态下
我们通过OP将ViewPager设置为正确的页面

解决方案

  • 在您的 RecyclerView.适配器
  • 使用HashMap将ViewPager的位置存储在 RecyclerView和相应的当前选定页面 寻呼机
  • 在onViewRecycled()方法中,将值输入到上面的 创建HashMap
  • 在onBindViewHolder()方法中,加载 使用位置从HashMap中选择ViewPager并设置保存的 使用setCurrentItem()方法将状态/页面设置为ViewPager

感谢Konstantin和atabouraya。

如果您使用的是
FragmentPagerAdapter
使用
FragmentStatePagerAdapter
不,我没有使用FragmentPagerAdapter,请使用状态感知适配器fx。我正在使用PagerAdapter。不确定基本PagerAdapter是否有任何状态感知适配器。您可以将当前项保存在
PagerAdapter
saveState()
方法中,然后在
restoreState()
中还原它?(这是一个猜测,我不知道这些方法是否可以用于此)您可以使用回收视图中的
public void onViewRecycled(VH holder)
方法,当适配器创建的视图被回收时,它将被调用。调用此方法时,您可以保存当前状态,您不再需要ViewWithViewPager:)@atabouraya fair point进行优化,改进了我的答案,谢谢!谢谢Konstantin和atabouraya。onViewRecycled()是我所需要的。它帮助我解决了这个问题。这可能会带来一些问题,好像你想删除或插入列表中的项目。因为您在ViewPageState中将recyclerview位置存储为键,所以每次插入或删除项目(或任何类型的项目订单更改)时您需要更新HashMap中的键,以使其与recyclerview本身保持同步。如果您的项目具有唯一的ID,那么我认为更好的方法是将这些ID用作viewPageStates HashMap中的键。这样,您就不必每次在recyclerview中发生项目订单更改时都更新键。此外,如果您的项目数少于几百个,您也可以使用SparseIntArray而不是HashMap来获得更好的性能。
public class ViewWithViewPager extends FrameLayout {

    ViewPager viewPager;
    int viewPosition = 0;

    public ViewWithViewPager(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.item_layout, this);
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPager.setAdapter(new ViewPagerAdapter());
    }

    public void refreshState(int position, int selectedPage) {
        viewPosition = position;
        viewPager.setCurrentItem(selectedPage);
    }
}