Reputation: 103
I have an issue with Recyclerview
item selection , which is set up in a fragment , the problem is each page which is created by ViewVager
has its own instance of the Recyclerview
so the output is that selecting Recyclerview
items will reset the scroll state of the Recyclerview
, so I'm looking for a solution to to save scroll state of a Recyclerview
when an item is clicked.
Fragment 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);
activity
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 adapter
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) {
// }
}
Upvotes: 1
Views: 988
Reputation: 21
try this
// save
recyclerViewState = binding.mainList.layoutManager?.onSaveInstanceState()
// restore
recyclerViewState?.let {
binding.mainList.layoutManager?.onRestoreInstanceState(it)
}
Upvotes: 2
Reputation: 40878
You can solve this by tracking the current scroll value of the RecyclerView
, and whenever you hit an a ReyclerView item; add a new parameter to the listener callback with this tracked scroll value to update the new fragment that will be shown on the ViewPager
.
Track the scroll value:
mEpisodesList.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
scrollValue += dx;
}
});
Pass it as interface callback:
planetAdapter = new PlanetAdapter(episodeslist, currentPosition, new PlanetAdapter.OnItemClickListener() {
@Override
public void onItemClick(final int pos) {
mCallback.sendText(pos, scrollValue);
}
});
And update that in the list of ViewPager
fragments before scrolling to the new page:
@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);
}
Upvotes: 1