【问题标题】:RecyclerView unwanted reloadsRecyclerView 不需要的重新加载
【发布时间】:2015-07-07 23:23:34
【问题描述】:

我有一个RecyclerView(垂直方向)和一个嵌套的ViewPager,用于水平滚动图片。

假设我在ViewPager 上水平滚动到最后一张图片。然后,我滚动RecyclerView 并触发加载下一个项目。在这里,ViewPager的图片回到第一张图片。

当适配器收到notifyDataSetChanged() 时,如何防止以前的ViewPager 项目返回到它们的第一张图片?

这是我整理的一个示例项目,只是为了展示这一点: https://github.com/alaouiali/BnbRecyclerView/

这是我的RecyclerView适配器和PageAdapter的代码

public class VerticalAdapter extends RecyclerView.Adapter<VerticalAdapter.ViewHolder> {
    /**
     * Contains the String used as a tag for the Log.d
     */
    private static final String TAG = VerticalAdapter.class.getSimpleName();
    private Context mContext;
    private String[] urls = {
            "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTqBvZfp5vUzdECuxydMqzkHbv8Io9kc_sGDh6Lb8t58ZEuTWfObw",
            "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcR6YRCpLYw6EAsJ8R3HsV5PzmJwVrmA1vZH9eX6-KEPVgbvnmp1VA",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTK3k3Mlj_RJQjUU3obJ2K-jAVTS4z-7elTaDxT1k9Q70Kg3Msd",

            "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSnD7v4HtlKQb2BWUoujS6W0T9I0NFcc9FjL9n7J2HnPcHszpUY",
            "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSX_yWO9qRV-tDPJ6dw17tzGFX3hrzJ47gclEkCnNZBzh-CLIgBTw",
            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQFSLufkwkiJbh9Wds3iCmljxxCFjngOsiKh7Ru_G-gJkMZ1dK_",

            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ_SJdCkLzFz-AM4hmj8fwQWLBbQ8uIe3C923IZAO2mcNdE8dCw",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjXskxWSam8FyCWND63SigsB6pMUg3GKfmPOJEWteahUexrPSB",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwGWksKf3P4nuVBOet_L75b_hgan_pnx-CNsuwOchVgZ-p2XGm",

            "https://c4.staticflickr.com/4/3366/4612778012_9c051789bf_b.jpg",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRoG9_j2RwXoUZFERhNz-lkQyHCUOgEvoDDVMky9yOaj88Lsc44",
            "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRxpM_iLl1d-MVOq5YT2LtHoxIqeU_H3_cDlkIVmAOYf0gVnV7g",

            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRLtZHrzluGj-EZcosXVni-Zmflqe4Fu1jGFSMVQAAzsdnS_2MeXw",
            "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcTKiUjsY-piPSuTA3mHfXAd7Zsg04m3lTw1IA1zKkJqnwKACiStwg",
            "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcROhycG7nOgvDzDOP2lBG37sk6wbHaYPbFX_pBx4FlbxtSM7Z2u",

            "https://c2.staticflickr.com/6/5099/5513125478_89d1729e3c_b.jpg",
            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTybyiNsOZrASdwsbcyl5SDh8aZyJdfVCjEJphTKA4Yf43dAfdknw",
            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTI7n06M_AHBFBkSwh7SLnC5OjEE6j0uSz-3mr5u_s8QA5SWjkk",

            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQUGJXi8BNyMSTEJcQHYqdl_8ABHd_ucuS0qeze8demczkzGUHbtA",
            "https://c3.staticflickr.com/7/6016/5984105136_7d5fa946b0_b.jpg",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTYPbn6L7Hw2_Lw01e5biRojnlFiviS566cqEuiY9H_7Y_Kr2VxeQ",

            "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcS-b3zNErmvMlbun8iDHOC4cZ6QC0sBchBIx6PsfFov_JSsMa4l",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRGcl15mygqfmdcgCmPlxr00-a87LJvTuEWuFp2xg_XI82fhfC-WQ",
            "https://c2.staticflickr.com/8/7251/6904099452_939e1ac5f2_b.jpg",

            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmz_u5DklKmUN4zbHiWWuGz46g8avWA7ajMgoDdicB9JF3lmAA",
            "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcR_lGkmwloEs9xZwJzzPZ7KlSp0oY5jTN-OtamC7rlEY8IhvGYO",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuzn6Ke_rwtWvktu8NTnMw1q-RlnR3SKevN0ITO_q2mWsv9i0G"
    };
    private List<ChildItem> createChildItems(int firstItem, int lastItem) {
        List<ChildItem> myDataset = new ArrayList<>();
        for(int i=firstItem; i < lastItem; i++) {
            //Log.d(TAG, "firstItem: "+firstItem+" i: "+i+" lastItem: "+lastItem);
            myDataset.add(new ChildItem("Number "+i, urls[i]));
        }
        return myDataset;
    }

    private static int mAppWidth;

    private List<ParentItem> mDataset;
    private List<ChildItem> mChildDataset;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;
        public ViewPager mViewPager;
        public ViewHolder(View v, Context context) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.text_bottom);
            mViewPager = (ViewPager) v.findViewById(R.id.view_pager);
            int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, v.getResources().getDisplayMetrics());
            mViewPager.getLayoutParams().height = (mAppWidth - px);
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public VerticalAdapter(Context context, List<ParentItem> myDataset, int appWidth) {
        mDataset = myDataset;
        mContext = context;
        mAppWidth = appWidth;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public VerticalAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.vertical_view, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder(v, mContext);

        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.mTextView.setText(mDataset.get(position).getText());
        mChildDataset = createChildItems(position*3,(position*3)+3);
        ImagePagerAdapter adapter = new ImagePagerAdapter(mChildDataset);
        holder.mViewPager.setAdapter(adapter);

    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    /**
     * ImagePagerAdapter to display images
     */
    private class ImagePagerAdapter extends PagerAdapter {

        List<ChildItem> mData;

        public ImagePagerAdapter(List<ChildItem> data) {
            mData = data;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Context context = mContext;
            ImageView mImageView = new ImageView(context);
            mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

            Picasso.with(context)
                    .load(mData.get(position).getUrl())
                    .placeholder(R.drawable.place_holder)
                    .error(R.drawable.place_holder_error)
                    .into(mImageView);

            ((ViewPager) container).addView(mImageView, 0);
            return mImageView;
        }

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

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == ((ImageView) object);
        }

        @Override
        public int getCount() {
            return mData.size();
        }
    }


}

【问题讨论】:

    标签: android android-viewpager android-recyclerview


    【解决方案1】:

    您需要将每个适配器的状态保存在主视图中。 所以试试这个。我只包含了相关代码,因此更容易理解。

    private final int[] childPos;
    
    // Provide a suitable constructor (depends on the kind of dataset)
    public VerticalAdapter(Context context, List<ParentItem> myDataset, int appWidth) {
    
        ...
    
        // assuming myDataset is a fixed size after 
        // its passed in. else u need to implement a variable list
        childPos = new int[mDataset.size()]; 
    }
    
    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
    
        ViewPager pager = holder.mViewPager;
        pager.setAdapter(adapter);
    
        // in case your adapter count changes;
        childPos[position] = childPos[position] < adapter.Count() ? childPos[position] : 0;
        final int trackPos = childPos[position];
    
        pager.setCurrentItem(holder.pos);
        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            }
    
            @Override
            public void onPageSelected(int position) {
                trackPos = position;
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        });
    }
    

    【讨论】:

    • 几乎可以工作!一个小问题:加载新项目时,它们会自动到达先前保存的位置。创建新项目时如何将当前位置重置为 0?谢谢
    • 抱歉没有考虑。 pos 应该存储在您的项目列表中,而不是查看器中。将每个项目的 pos 保存在 private List mDataset;
    • 我开始尝试实现一个列表,因为我的数据集是可变的。我已经提交了我的代码,但是在执行 childPos.get(position) 时我得到了 java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
    • 将 childpos 添加为 ParentItem 类的运行时成员,并从那里访问它。
    猜你喜欢
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    相关资源
    最近更新 更多