RecyclerView перетасовки предметов
Я знаю, что этот вопрос задавался несколько раз, но проблема все еще присутствует. Так что дело в том, что когда я прокручиваю свою вертикаль RecyclerView
элементы списка внутри ViewHolder
тасуются. У меня есть список некоторых объектов с логическим внутри него, решая ViewType
так что я могу раздувать разные взгляды. Итак, вот код:
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == TYPE_ACTIVE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_poll_item_active, parent, false);
return new CardViewHolderActive(view);
} else if(viewType == TYPE_INACTIVE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_poll_item_past, parent, false);
return new CardViewHolderPast(view);
}
throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Poll poll = mListPollObjects.get(position);
Log.d("ADAPTER", "position - " + position);
if(holder instanceof CardViewHolderActive) {
((CardViewHolderActive) holder).bindActivePolls(poll);
} else if(holder instanceof CardViewHolderPast) {
if(position == 0) {
((CardViewHolderPast) holder).bindPastPolls(poll, true);
} else if(getItemViewType(position - 1) == TYPE_INACTIVE) {
((CardViewHolderPast) holder).bindPastPolls(poll, false);
} else if(getItemViewType(position - 1) == TYPE_ACTIVE)
((CardViewHolderPast) holder).bindPastPolls(poll, true);
}
}
@Override
public int getItemCount() {
return mListPollObjects.size();
}
/**
* Added to solve the RecyclerView shuffling problem.
*
* @param position
* @return
*/
@Override
public long getItemId(int position) {
return position;
}
/**
* Added to solve the RecyclerView shuffling problem.
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
Poll poll = mListPollObjects.get(position);
if(poll.getStatus().equals(Poll.STATUS_ACTIVE)) {
return TYPE_ACTIVE;
} else {
return TYPE_INACTIVE;
}
}
Итак, когда у меня было:
@Override
public int getItemViewType(int position) {
return position;
}
перетасовка исчезла, однако я должен был сделать обязательные вещи в onBindViewHolder
все вручную, поэтому я решил переключиться на viewTypes
, Я действительно не могу понять, что здесь происходит, и это довольно раздражает... Надеюсь, я предоставил достаточно информации. Заранее спасибо!
Здесь bindActivePolls
метод из CardViewHolderActive
:
public void bindActivePolls(final Poll polls) {
int listImageSize = polls.getListImageObjects().size();
//tvPollTitle.setText(polls.getStatus() + " - " + polls.getId());
if(polls.getTitle() != null || !polls.getTitle().equals("")) {
tvPollTitle.setText(polls.getTitle());
} else {
tvPollTitle.setText("");
}
tvCurrentVotes.setText(String.valueOf(polls.getVotesCount()) + "/");
tvUpToVotes.setText(String.valueOf(polls.getMaxVotes()));
// Setting the percentage bars.
pbProgressOne.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(0).getVotes()));
tvProgressOne.setText(String.valueOf(pbProgressOne.getProgress()) + mContext.getString(R.string.percentage));
pbProgressTwo.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(1).getVotes()));
tvProgressTwo.setText(String.valueOf(pbProgressTwo.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(0).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageOne);
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(1).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageTwo);
if(listImageSize >= 3) {
pbProgressThree.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(2).getVotes()));
tvProgressThree.setText(String.valueOf(pbProgressThree.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(2).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageThree);
}
if(listImageSize >= 4) {
pbProgressFour.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(3).getVotes()));
tvProgressFour.setText(String.valueOf(pbProgressFour.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(3).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageFour);
}
}
А также bindPastPolls()
от CardViewHolderPast
:
public void bindPastPolls(Poll polls, boolean isFirstPast) {
if(isFirstPast) {
vSeparator.setVisibility(View.VISIBLE);
tvPastContestSeparator.setVisibility(View.VISIBLE);
}
int listImageSize = polls.getListImageObjects().size();
//tvPollTitle.setText(polls.getStatus() + " - " + polls.getId());
if(polls.getTitle() != null || !polls.getTitle().equals("")) {
tvPollTitle.setText(polls.getTitle());
} else {
tvPollTitle.setText("");
}
tvCurrentVotes.setText(String.valueOf(polls.getVotesCount()) + "/");
tvUpToVotes.setText(String.valueOf(polls.getMaxVotes()));
pbProgressOne.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(0).getVotes()));
tvProgressOne.setText(String.valueOf(pbProgressOne.getProgress()) + mContext.getString(R.string.percentage));
pbProgressTwo.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(1).getVotes()));
tvProgressTwo.setText(String.valueOf(pbProgressTwo.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(0).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageOne);
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(1).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageTwo);
if(listImageSize >= 3) {
pbProgressThree.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(2).getVotes()));
tvProgressThree.setText(String.valueOf(pbProgressThree.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(2).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageThree);
}
if(listImageSize >= 4) {
pbProgressFour.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(3).getVotes()));
tvProgressFour.setText(String.valueOf(pbProgressFour.getProgress()) + mContext.getString(R.string.percentage));
GlideApp.with(mContext)
.asDrawable()
.load(polls.getListImageObjects().get(3).getUrlImageMainThumbnail())
.transforms(new CenterCrop(), new RoundedCorners(20))
.into(ivImageFour);
}
}
Обновление: когда я установил holder.setIsRecyclable(false)
это работает должным образом, но я предполагаю, что теряет свое основное назначение RecyclerView?
2 ответа
У меня тоже была эта проблема несколько лет назад, и это потому, что я использовал glide, если есть изображение из API, а если нет, то я не устанавливал изображение. Я добавил оператор else, чтобы указать src для представления изображения. Если вы хотите, чтобы он был пустым, установите src, который соответствует фону.
В Java
@Override
public int getItemViewType(int position)
{
return position;
}
В Котлине
override fun getItemViewType(position: Int): Int = position