【问题标题】:How to save scroll state of a Recyclerview when an item is clicked?单击项目时如何保存Recyclerview的滚动状态?
【发布时间】:2021-07-06 23:53:27
【问题描述】:

我在片段中设置的Recyclerview 项目选择存在问题,问题是ViewVager 创建的每个页面都有自己的Recyclerview 实例,因此输出是选择@ 987654324@ 项目将重置 Recyclerview 的滚动状态,因此我正在寻找一种解决方案来在单击项目时保存 Recyclerview 的滚动状态。

片段 onViewCreated

// setting RecyclerView
            mEpisodesList = (CustomRecyclerView) view.findViewById(R.id.episodesLIST);
    
    
            // getting episodeslist
            ArrayList<PlanetModel> episodeslist = new ArrayList<>();
    
            for (TvShowEpisode e : mEpisodes) {
                episodeslist.add(new PlanetModel(e.mEpisode));
            }
    
    
            // Setting LinearLayoutManager
            LinearLayoutManager layoutManager
                    = new LinearLayoutManager(mContext.getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
            //mEpisodesList.setLayoutManager(new LinearLayoutManager(mContext));
            mEpisodesList.setLayoutManager(layoutManager);
    
    
            // Setting RecyclerView Adapter
            int currentPosition = getArguments().getInt("position");
            planetAdapter = new PlanetAdapter(episodeslist, currentPosition, new PlanetAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(final int pos) {
                    int scrollValue = mEpisodesList.getHorizontalScrollOffset();
                    mCallback.sendText(pos, scrollValue);
                }
            });
            mEpisodesList.setAdapter(planetAdapter);
    
            int scrollValue = getArguments().getInt("scrollValue");
            new Handler().postDelayed(() -> mEpisodesList.scrollBy(scrollValue, 0), 100);

活动

    public class TvShowEpisodeDetails extends MizActivity implements TvShowEpisodeDetailsFragment.TextClicked {
    
    
        @Override
        protected int getLayoutResource() {
            return R.layout.viewpager_with_toolbar_overlay;
        }
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            mBus = MizuuApplication.getBus();
            super.onCreate(savedInstanceState);
    
            // Set theme
            setTheme(R.style.Mizuu_Theme_NoBackground);
    
            ViewUtils.setupWindowFlagsForStatusbarOverlay(getWindow(), true);
    
            ViewUtils.setProperToolbarSize(this, mToolbar);
    
            mShowId = getIntent().getExtras().getString(SHOW_ID);
            mSeason = getIntent().getExtras().getInt("season");
            mEpisode = getIntent().getExtras().getInt("episode");
    
            mDatabaseHelper = MizuuApplication.getTvEpisodeDbAdapter();
    
            Cursor cursor = mDatabaseHelper.getEpisodes(mShowId);
            try {
                while (cursor.moveToNext()) {
                    mEpisodes.add(new TvShowEpisode(this, mShowId,
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_TITLE)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_PLOT)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_SEASON)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_AIRDATE)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_DIRECTOR)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_WRITER)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_GUESTSTARS)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_EPISODE_RATING)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_HAS_WATCHED)),
                            cursor.getString(cursor.getColumnIndex(DbAdapterTvShowEpisodes.KEY_FAVOURITE))
                    ));
                }
            } catch (Exception e) {
            } finally {
                cursor.close();
            }
    
    
            final ArrayList<PlanetModel> episodeslist = new ArrayList<>();
    
            for (TvShowEpisode e : mEpisodes) {
                episodeslist.add(new PlanetModel(e.mEpisode));
            }
    
            mShowTitle = MizuuApplication.getTvDbAdapter().getShowTitle(mShowId);
            setTitle(mShowTitle);
    
            mViewPager = (ViewPager) findViewById(R.id.awesomepager);
            mViewPager.setAdapter(new TvShowEpisodeDetailsAdapter(getSupportFragmentManager()));
    
            for (int i = 0; i < mEpisodes.size(); i++)
                fragments.add(TvShowEpisodeDetailsFragment
                        .newInstance(mShowId, Integer.parseInt(mEpisodes.get(i).getSeason()), Integer.parseInt(mEpisodes.get(i).getEpisode()), i, mScrollValue));
    
            mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    for (int i = 0; i < episodeslist.size(); i++) {
                        episodeslist.get(i).setPlanetSelected(false);
                    }
                    episodeslist.get(position).setPlanetSelected(true);
                    //notify your recycler views adaper
                    ViewUtils.updateToolbarBackground(TvShowEpisodeDetails.this, mToolbar, 0, mEpisodes.get(position).getTitle(), Color.TRANSPARENT);
    
    
                }
            });
    
            if (savedInstanceState != null) {
                mViewPager.setCurrentItem(savedInstanceState.getInt("tab", 0));
            } else {
                for (int i = 0; i < mEpisodes.size(); i++) {
                    if (mEpisodes.get(i).getSeason().equals(MizLib.addIndexZero(mSeason)) && mEpisodes.get(i).getEpisode().equals(MizLib.addIndexZero(mEpisode))) {
                        mViewPager.setCurrentItem(i);
                        SharedPreferences setPref = this.getSharedPreferences("TvShowEpisodeDetails", Context.MODE_PRIVATE);
                        setPref.edit().putInt("i", i).apply();
                        break;
                    }
                }
            }
        }
    
        
    
        private class TvShowEpisodeDetailsAdapter extends FragmentPagerAdapter {
    
            public TvShowEpisodeDetailsAdapter(FragmentManager fm) {
                super(fm);
            }
    
            @Override
            public Fragment getItem(int index) {
    //            return TvShowEpisodeDetailsFragment.newInstance(mShowId, Integer.parseInt(mEpisodes.get(index).getSeason()), Integer.parseInt(mEpisodes.get(index).getEpisode()));
    
                return fragments.get(index);
            }
    
            @Override
            public int getCount() {
                return mEpisodes.size();
            }
        }

Recyclerview 适配器

public class PlanetAdapter extends RecyclerView.Adapter<PlanetAdapter.PlanetViewHolder> {

    public interface OnItemClickListener {
        void onItemClick(int item);
    }

    private final ArrayList<PlanetModel> episodeslist;
    private final OnItemClickListener listener;
    SharedPreferences getPref = getContext().getSharedPreferences("TvShowEpisodeDetails", Context.MODE_PRIVATE);
    int pos = getPref.getInt("i", 0);

    int isPlanetSelected = pos;

    private final int highlightedPos;
    public PlanetAdapter(ArrayList<PlanetModel> episodeslist, int highlightedPosition, OnItemClickListener listener) {
        this.episodeslist = episodeslist;
        this.listener = listener;
        this.highlightedPos = highlightedPosition;
    }

    @NonNull
    @Override
    public PlanetAdapter.PlanetViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.planet_row, parent, false);
        return new PlanetViewHolder(v);
    }

    @Override
    public void onBindViewHolder(PlanetAdapter.PlanetViewHolder vh, final int position) {
        TextView tv = (TextView) vh.itemView;
        PlanetModel planetModel = episodeslist.get(position);
        tv.setText(planetModel.getPlanetName());
        tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.bg, 0, 0, 0);

        if (highlightedPos == position) {
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryLight));

        } else {
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryDark));
        }

//holder.image.setImageResource(R.drawable.planetimage);
//vh.text.setText(episodeslist.get(position).toString());
    }

    @Override
    public int getItemCount() {
        return episodeslist.size();
    }

    public class PlanetViewHolder extends RecyclerView.ViewHolder {

        protected TextView text;

        public PlanetViewHolder(View itemView) {
            super(itemView);
            text = (TextView) itemView.findViewById(R.id.text_id);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d("LOG_TAG", "onClick: current item: " + highlightedPos);
                    final int previousItem = isPlanetSelected;
                    isPlanetSelected = getPosition();
                    SharedPreferences setPref = v.getContext().getSharedPreferences("PlanetAdapter", Context.MODE_PRIVATE);
                    setPref.edit().putInt("newPosition", getPosition()).apply();
                    listener.onItemClick(getPosition());
                }
            });

        }

// public void bind(final PlanetModel item, final OnItemClickListener listener) {
// }
    }

【问题讨论】:

  • @Zain ,滚动状态仍然不符合预期
  • 请注意您使用的是已弃用的 API。support.v7.widget.recyclerview 中的 computeverticalscrolloffset() 具有受保护的访问权限,因此您可以创建子类来访问它或使用我在回答
  • @Zain 谢谢先生,mEpisodesList.scrollBy(scrollValue, 0), 100) 在我这边不起作用,但我从头开始重新安装了所有东西,我这边会不会有某种错误?
  • @Zain 先生,我试了 100、200、300,还是一样

标签: java android-fragments android-recyclerview scroll android-viewpager


【解决方案1】:

您可以通过跟踪RecyclerView 的当前滚动值以及每当您点击 ReyclerView 项目来解决此问题;使用此跟踪滚动值向侦听器回调添加一个新参数,以更新将在ViewPager 上显示的新片段。

跟踪滚动值:

    mEpisodesList.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            scrollValue += dx;
        }
    });

作为接口回调传递:

    planetAdapter = new PlanetAdapter(episodeslist, currentPosition, new PlanetAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(final int pos) {
            mCallback.sendText(pos, scrollValue);
        }
    });

并在滚动到新页面之前更新 ViewPager 片段列表中的内容:

@Override
public void sendText(int position, int scrollValue) {
    mScrollValue = scrollValue;
    TvShowEpisodeDetailsFragment frag = fragments.get(position);
    Bundle arguments = frag.getArguments();
    arguments.putInt("scrollValue", scrollValue);
    mViewPager.setCurrentItem(position, false);
}

【讨论】:

  • 先生,非常感谢,我应用了答案,但所选项目仍然不在屏幕上,这是一个视频On tap,这是一个视频On Swipe
  • @Steve 尝试将其替换为 mEpisodesList.setScrollX(scrollValue)mEpisodesList.scrollTo(scrollValue, 0)
  • 还有smoothScrollBy(scrollValue, 0)
  • 存储桶中的最后一个:int position = getArguments().getInt("position"); ((LinearLayoutManager) mEpisodesList.getLayoutManager()).scrollToPositionWithOffset(position, scrollValue);
  • 但是我不得不说,先生,您已经尽力了,我非常感谢,我必须对此感到满意,再次我真的很感激
猜你喜欢
  • 2019-09-27
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
相关资源
最近更新 更多