OnBindViewHolder:为什么有时位置不从零开始?
OnBindViewHolder: why sometimes position don't start from zero?
我正在使用 RecyclerView,我注意到一个奇怪的行为:每次 onBindViewHolder()
被调用时我都会记录实际位置,有时位置不是从零开始的,你知道为什么吗?对我来说这是一个问题,因为在位置 0 我有不同的逻辑。
那是记录器:
2022-02-15 16:19:51.833 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:19:51.834 D/UpdateFragment: >>>ViewModel.GetAllTags()
2022-02-15 16:19:51.864 D/RecyclerViewAdapterUpdate: >>>Position:0
2022-02-15 16:19:52.110 D/RecyclerViewAdapterUpdate: >>>Position:1
2022-02-15 16:19:52.266 D/RecyclerViewAdapterUpdate: >>>Position:2
2022-02-15 16:19:52.331 D/RecyclerViewAdapterUpdate: >>>Position:3
2022-02-15 16:20:03.696 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.722 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.729 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.729 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.730 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.737 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.743 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.750 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.761 D/RecyclerViewAdapterUpdate: >>>Position:2
2022-02-15 16:20:03.830 D/RecyclerViewAdapterUpdate: >>>Position:3
2022-02-15 16:20:03.891 D/RecyclerViewAdapterUpdate: >>>Position:1
2022-02-15 16:20:04.042 D/RecyclerViewAdapterUpdate: >>>Position:0
好的,我知道顺序并不总是相同,但在我的应用程序中,当我更新数据时,我注意到 2 个 ViewHolder 的布局之间存在神秘的交换,但在我的代码中我从未将布局分配给视图持有者。正如您在日志中看到的,与位置相关联的布局的 id 发生了变化。
2022-02-15 19:03:10.878 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:11.593 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:11.954 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{61b8127 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:18.326 D/RecyclerViewAdapterUpdate: >>>View android.widget.LinearLayout{61b8127 V.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}true
2022-02-15 19:03:18.953 D/RecyclerViewAdapterUpdate: >>>View androidx.constraintlayout.widget.ConstraintLayout{8510217 V.E...... ......I. 0,0-0,0 #7f08021e app:id/layout_update_card}true
2022-02-15 19:03:53.394 D/RecyclerViewAdapterUpdate: >>>Saved
2022-02-15 19:03:53.582 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:53.729 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.005 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,761 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.437 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,378 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.695 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.879 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Log.d(TAG, ">>>Position["+position+"]" + holder.linearLayout);
if (position == 0) {
// All the cards
holder.numberOfItems.setText(String.valueOf(cardList.size()));
holder.tagName.setText(R.string.all_cards_tag);
holder.clearTag.setVisibility(View.GONE); // Can't delete all cards
holder.checkBox.setChecked(allCardIsChecked);
holder.checkBox.setOnClickListener(view -> {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
if (holder.checkBox.isChecked()) {
MainActivity.recyclerTagList.clear();
editor.putStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
numberOfSelected = 1;
if (!allCardIsChecked) {
allCardIsChecked = true;
notifyDataSetChanged();
}
} else {
// Can't deselect all cards, at least one group chosen
holder.checkBox.setChecked(true);
Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
}
editor.commit();
});
initializeLayoutCards(cardList,null, holder, true);
} else {
// Single TAG after all cards
Tag tag = tagList.get(position - 1);
List<CardWithTags> listOfSingleTag = new ArrayList<>();
for (CardWithTags cwt: cardList) {
for (Tag t: cwt.getTagList()) {
if (t.getTag().equals(tag.getTag()))
listOfSingleTag.add(cwt);
}
}
initializeLayoutCards(listOfSingleTag, tag, holder, false);
holder.numberOfItems.setText(String.valueOf(listOfSingleTag.size()));
holder.tagName.setText(tag.getTag());
holder.clearTag.setVisibility(View.VISIBLE);
if (allCardIsChecked)
holder.checkBox.setChecked(false);
else {
holder.checkBox.setChecked(false);
for (String s: selectedTags) {
if (s.equalsIgnoreCase(tag.getTag()))
holder.checkBox.setChecked(true);
}
}
holder.checkBox.setOnClickListener(view -> {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
if (holder.checkBox.isChecked()) {
MainActivity.recyclerTagList.add(tag);
selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
selectedTags.add(tag.getTag());
editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
if (allCardIsChecked) {
allCardIsChecked = false;
notifyDataSetChanged();
} else {
++numberOfSelected;
}
} else {
if (numberOfSelected == 1) {
Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
holder.checkBox.setChecked(true);
}
else {
--numberOfSelected;
MainActivity.recyclerTagList.removeIf(t -> t.getTag().equalsIgnoreCase(tag.getTag()));
selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
selectedTags.remove(tag.getTag());
editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
}
}
editor.commit();
});
View viewDialogTag = LayoutInflater.from(context).inflate(R.layout.dialog_modify_tag, (ViewGroup) null);
EditText tagNameEditText = viewDialogTag.findViewById(R.id.tag_name_dialog);
tagNameEditText.setText(tag.getTag());
// In this way the dialog is created only one time
AlertDialog dialogTag = getDialogUpdateTag(tag, viewDialogTag, tagNameEditText);
AlertDialog dialogDeleteTag = getDialogDeleteTag(tag);
holder.tagName.setOnLongClickListener( view -> {
// Change tag name only if closed
if (holder.linearLayout.getVisibility() == View.GONE)
dialogTag.show();
return true;
});
holder.clearTag.setOnClickListener( view -> dialogDeleteTag.show());
}
}
private void initializeLayoutCards(List<CardWithTags> cardList, Tag tag, ViewHolder holder, boolean isAllCards) {
// Or it will add already added cards
holder.linearLayout.removeAllViews();
for (CardWithTags cwt : cardList) {
Card card = cwt.getCard();
View cardView = LayoutInflater.from(context).inflate(R.layout.card_update, holder.linearLayout, false);
TextView textViewCardName = cardView.findViewById(R.id.card_name);
Button clearButton = cardView.findViewById(R.id.clear_card);
ConstraintLayout layoutCardUpdate = cardView.findViewById(R.id.layout_update_card);
EditText titleEditText = cardView.findViewById(R.id.update_title_edit_text);
EditText taboo1EditText = cardView.findViewById(R.id.update_taboo_1_edit_text);
EditText taboo2EditText = cardView.findViewById(R.id.update_taboo_2_edit_text);
EditText taboo3EditText = cardView.findViewById(R.id.update_taboo_3_edit_text);
EditText taboo4EditText = cardView.findViewById(R.id.update_taboo_4_edit_text);
EditText taboo5EditText = cardView.findViewById(R.id.update_taboo_5_edit_text);
Button saveButton = cardView.findViewById(R.id.save_button);
Button tagButton = cardView.findViewById(R.id.tag_button);
textViewCardName.setText(card.getTitle());
titleEditText.setText(card.getTitle());
taboo1EditText.setText(card.getTabooWord1());
taboo2EditText.setText(card.getTabooWord2());
taboo3EditText.setText(card.getTabooWord3());
taboo4EditText.setText(card.getTabooWord4());
taboo5EditText.setText(card.getTabooWord5());
saveButton.setOnClickListener(view -> {
Animations.doReduceIncreaseAnimation(view);
String title = titleEditText.getText().toString();
String taboo1 = taboo1EditText.getText().toString();
String taboo2 = taboo2EditText.getText().toString();
String taboo3 = taboo3EditText.getText().toString();
String taboo4 = taboo4EditText.getText().toString();
String taboo5 = taboo5EditText.getText().toString();
if (title.equalsIgnoreCase(card.getTitle()) &&
taboo1.equalsIgnoreCase(card.getTabooWord1()) &&
taboo2.equalsIgnoreCase(card.getTabooWord2()) &&
taboo3.equalsIgnoreCase(card.getTabooWord3()) &&
taboo4.equalsIgnoreCase(card.getTabooWord4()) &&
taboo5.equalsIgnoreCase(card.getTabooWord5())) {
Log.d(TAG, ">>Change something before saving card");
return;
}
Card newCard = new Card(title, taboo1, taboo2, taboo3, taboo4, taboo5);
newCard.setIdCard(card.getIdCard());
// Check if new title already exists
for (CardWithTags c: this.cardList) {
if (!c.getCard().getTitle().equalsIgnoreCase(card.getTitle()) && c.getCard().getTitle().equalsIgnoreCase(title)) {
Toast.makeText(context, R.string.title_already_exists, Toast.LENGTH_SHORT).show();
return;
}
}
cwt.setCard(newCard);
Log.d(TAG, ">>New cwt: " + cwt);
Log.d(TAG, ">>>Saved");
viewModelFragment.updateCWT(cwt);
Toast.makeText(context, R.string.card_updated, Toast.LENGTH_SHORT).show();
});
tagButton.setOnClickListener(view -> {
Animations.doReduceIncreaseAnimation(view);
});
textViewCardName.setOnClickListener(view -> {
openCloseView(layoutCardUpdate);
});
AlertDialog dialogDeleteCard;
if (!isAllCards)
dialogDeleteCard = getDialogDeleteCardOrTag(card, tag);
else
dialogDeleteCard = getDialogDeleteCard(card);
clearButton.setOnClickListener(view -> dialogDeleteCard.show());
// Set the click on both number of items and tag name
holder.tagName.setOnClickListener(view -> {
openCloseView(holder.linearLayout);
});
holder.numberOfItems.setOnClickListener(view -> {
openCloseView(holder.linearLayout);
});
holder.linearLayout.addView(cardView);
}
}
private void openCloseView(View view) {
if (view.getVisibility() == View.GONE) {
view.setVisibility(View.VISIBLE);
boolean isVisible = view.getVisibility() == View.VISIBLE? true : false;
Log.d(TAG, ">>>View " + view +isVisible);
AnimationSet animation = new AnimationSet(true);
Animation animationAlpha = new AlphaAnimation(0, 1);
animation.addAnimation(animationAlpha);
Animation animationTranslate = new TranslateAnimation(0, 0, -view.getHeight(), 0);
animation.addAnimation(animationTranslate);
Animation animationY = new ScaleAnimation(1, 1, 0, 1);
animationY.setInterpolator(new LinearInterpolator());
animation.addAnimation(animationY);
animation.setDuration(200);
view.startAnimation(animation);
} else {
AnimationSet animation = new AnimationSet(true);
Animation animationAlpha = new AlphaAnimation(1, 0);
animation.addAnimation(animationAlpha);
Animation animationTranslate = new TranslateAnimation(0, 0, 0, -view.getHeight());
animation.addAnimation(animationTranslate);
Animation animationY = new ScaleAnimation(1, 1, 1, 0);
animationY.setInterpolator(new LinearInterpolator());
animation.addAnimation(animationY);
animation.setDuration(200);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
boolean isVisible = view.getVisibility() == View.VISIBLE;
Log.d(TAG, ">>>View " + view +isVisible);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
view.startAnimation(animation);
}
}
只绑定屏幕上需要更新的项目。事实上,该组件会尽量减少 onbind 调用的次数,以防止额外的工作。没有承诺的调用顺序。因此,唯一一次 0 被确保被调用是在第一次加载时——即使在这种情况下它也不会被调用(例如,如果你正在进行反向填充并从底部开始)。如果您在编写代码时假设它总是尝试绑定 0,那么您就误解了 RecyclerView 的工作原理,需要重新评估您的设计。
为了解决我的问题,我使用 SharedPreferences 在视图是否可见时输入一个布尔值,然后在 onBindViewHolder()
中检索该数据并设置可见性。
我正在使用 RecyclerView,我注意到一个奇怪的行为:每次 onBindViewHolder()
被调用时我都会记录实际位置,有时位置不是从零开始的,你知道为什么吗?对我来说这是一个问题,因为在位置 0 我有不同的逻辑。
那是记录器:
2022-02-15 16:19:51.833 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:19:51.834 D/UpdateFragment: >>>ViewModel.GetAllTags()
2022-02-15 16:19:51.864 D/RecyclerViewAdapterUpdate: >>>Position:0
2022-02-15 16:19:52.110 D/RecyclerViewAdapterUpdate: >>>Position:1
2022-02-15 16:19:52.266 D/RecyclerViewAdapterUpdate: >>>Position:2
2022-02-15 16:19:52.331 D/RecyclerViewAdapterUpdate: >>>Position:3
2022-02-15 16:20:03.696 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.722 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.729 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.729 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.730 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.737 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.743 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.750 D/UpdateFragment: >>>ViewModel.GetAllCards()
2022-02-15 16:20:03.761 D/RecyclerViewAdapterUpdate: >>>Position:2
2022-02-15 16:20:03.830 D/RecyclerViewAdapterUpdate: >>>Position:3
2022-02-15 16:20:03.891 D/RecyclerViewAdapterUpdate: >>>Position:1
2022-02-15 16:20:04.042 D/RecyclerViewAdapterUpdate: >>>Position:0
好的,我知道顺序并不总是相同,但在我的应用程序中,当我更新数据时,我注意到 2 个 ViewHolder 的布局之间存在神秘的交换,但在我的代码中我从未将布局分配给视图持有者。正如您在日志中看到的,与位置相关联的布局的 id 发生了变化。
2022-02-15 19:03:10.878 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:11.593 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:11.954 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{61b8127 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:18.326 D/RecyclerViewAdapterUpdate: >>>View android.widget.LinearLayout{61b8127 V.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}true
2022-02-15 19:03:18.953 D/RecyclerViewAdapterUpdate: >>>View androidx.constraintlayout.widget.ConstraintLayout{8510217 V.E...... ......I. 0,0-0,0 #7f08021e app:id/layout_update_card}true
2022-02-15 19:03:53.394 D/RecyclerViewAdapterUpdate: >>>Saved
2022-02-15 19:03:53.582 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:53.729 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.005 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,761 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.437 D/RecyclerViewAdapterUpdate: >>>Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,378 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.695 D/RecyclerViewAdapterUpdate: >>>Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
2022-02-15 19:03:54.879 D/RecyclerViewAdapterUpdate: >>>Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Log.d(TAG, ">>>Position["+position+"]" + holder.linearLayout);
if (position == 0) {
// All the cards
holder.numberOfItems.setText(String.valueOf(cardList.size()));
holder.tagName.setText(R.string.all_cards_tag);
holder.clearTag.setVisibility(View.GONE); // Can't delete all cards
holder.checkBox.setChecked(allCardIsChecked);
holder.checkBox.setOnClickListener(view -> {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
if (holder.checkBox.isChecked()) {
MainActivity.recyclerTagList.clear();
editor.putStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
numberOfSelected = 1;
if (!allCardIsChecked) {
allCardIsChecked = true;
notifyDataSetChanged();
}
} else {
// Can't deselect all cards, at least one group chosen
holder.checkBox.setChecked(true);
Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
}
editor.commit();
});
initializeLayoutCards(cardList,null, holder, true);
} else {
// Single TAG after all cards
Tag tag = tagList.get(position - 1);
List<CardWithTags> listOfSingleTag = new ArrayList<>();
for (CardWithTags cwt: cardList) {
for (Tag t: cwt.getTagList()) {
if (t.getTag().equals(tag.getTag()))
listOfSingleTag.add(cwt);
}
}
initializeLayoutCards(listOfSingleTag, tag, holder, false);
holder.numberOfItems.setText(String.valueOf(listOfSingleTag.size()));
holder.tagName.setText(tag.getTag());
holder.clearTag.setVisibility(View.VISIBLE);
if (allCardIsChecked)
holder.checkBox.setChecked(false);
else {
holder.checkBox.setChecked(false);
for (String s: selectedTags) {
if (s.equalsIgnoreCase(tag.getTag()))
holder.checkBox.setChecked(true);
}
}
holder.checkBox.setOnClickListener(view -> {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
if (holder.checkBox.isChecked()) {
MainActivity.recyclerTagList.add(tag);
selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
selectedTags.add(tag.getTag());
editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
if (allCardIsChecked) {
allCardIsChecked = false;
notifyDataSetChanged();
} else {
++numberOfSelected;
}
} else {
if (numberOfSelected == 1) {
Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
holder.checkBox.setChecked(true);
}
else {
--numberOfSelected;
MainActivity.recyclerTagList.removeIf(t -> t.getTag().equalsIgnoreCase(tag.getTag()));
selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet<>());
selectedTags.remove(tag.getTag());
editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
Log.d(TAG, ">>Tags selected: " + MainActivity.recyclerTagList);
}
}
editor.commit();
});
View viewDialogTag = LayoutInflater.from(context).inflate(R.layout.dialog_modify_tag, (ViewGroup) null);
EditText tagNameEditText = viewDialogTag.findViewById(R.id.tag_name_dialog);
tagNameEditText.setText(tag.getTag());
// In this way the dialog is created only one time
AlertDialog dialogTag = getDialogUpdateTag(tag, viewDialogTag, tagNameEditText);
AlertDialog dialogDeleteTag = getDialogDeleteTag(tag);
holder.tagName.setOnLongClickListener( view -> {
// Change tag name only if closed
if (holder.linearLayout.getVisibility() == View.GONE)
dialogTag.show();
return true;
});
holder.clearTag.setOnClickListener( view -> dialogDeleteTag.show());
}
}
private void initializeLayoutCards(List<CardWithTags> cardList, Tag tag, ViewHolder holder, boolean isAllCards) {
// Or it will add already added cards
holder.linearLayout.removeAllViews();
for (CardWithTags cwt : cardList) {
Card card = cwt.getCard();
View cardView = LayoutInflater.from(context).inflate(R.layout.card_update, holder.linearLayout, false);
TextView textViewCardName = cardView.findViewById(R.id.card_name);
Button clearButton = cardView.findViewById(R.id.clear_card);
ConstraintLayout layoutCardUpdate = cardView.findViewById(R.id.layout_update_card);
EditText titleEditText = cardView.findViewById(R.id.update_title_edit_text);
EditText taboo1EditText = cardView.findViewById(R.id.update_taboo_1_edit_text);
EditText taboo2EditText = cardView.findViewById(R.id.update_taboo_2_edit_text);
EditText taboo3EditText = cardView.findViewById(R.id.update_taboo_3_edit_text);
EditText taboo4EditText = cardView.findViewById(R.id.update_taboo_4_edit_text);
EditText taboo5EditText = cardView.findViewById(R.id.update_taboo_5_edit_text);
Button saveButton = cardView.findViewById(R.id.save_button);
Button tagButton = cardView.findViewById(R.id.tag_button);
textViewCardName.setText(card.getTitle());
titleEditText.setText(card.getTitle());
taboo1EditText.setText(card.getTabooWord1());
taboo2EditText.setText(card.getTabooWord2());
taboo3EditText.setText(card.getTabooWord3());
taboo4EditText.setText(card.getTabooWord4());
taboo5EditText.setText(card.getTabooWord5());
saveButton.setOnClickListener(view -> {
Animations.doReduceIncreaseAnimation(view);
String title = titleEditText.getText().toString();
String taboo1 = taboo1EditText.getText().toString();
String taboo2 = taboo2EditText.getText().toString();
String taboo3 = taboo3EditText.getText().toString();
String taboo4 = taboo4EditText.getText().toString();
String taboo5 = taboo5EditText.getText().toString();
if (title.equalsIgnoreCase(card.getTitle()) &&
taboo1.equalsIgnoreCase(card.getTabooWord1()) &&
taboo2.equalsIgnoreCase(card.getTabooWord2()) &&
taboo3.equalsIgnoreCase(card.getTabooWord3()) &&
taboo4.equalsIgnoreCase(card.getTabooWord4()) &&
taboo5.equalsIgnoreCase(card.getTabooWord5())) {
Log.d(TAG, ">>Change something before saving card");
return;
}
Card newCard = new Card(title, taboo1, taboo2, taboo3, taboo4, taboo5);
newCard.setIdCard(card.getIdCard());
// Check if new title already exists
for (CardWithTags c: this.cardList) {
if (!c.getCard().getTitle().equalsIgnoreCase(card.getTitle()) && c.getCard().getTitle().equalsIgnoreCase(title)) {
Toast.makeText(context, R.string.title_already_exists, Toast.LENGTH_SHORT).show();
return;
}
}
cwt.setCard(newCard);
Log.d(TAG, ">>New cwt: " + cwt);
Log.d(TAG, ">>>Saved");
viewModelFragment.updateCWT(cwt);
Toast.makeText(context, R.string.card_updated, Toast.LENGTH_SHORT).show();
});
tagButton.setOnClickListener(view -> {
Animations.doReduceIncreaseAnimation(view);
});
textViewCardName.setOnClickListener(view -> {
openCloseView(layoutCardUpdate);
});
AlertDialog dialogDeleteCard;
if (!isAllCards)
dialogDeleteCard = getDialogDeleteCardOrTag(card, tag);
else
dialogDeleteCard = getDialogDeleteCard(card);
clearButton.setOnClickListener(view -> dialogDeleteCard.show());
// Set the click on both number of items and tag name
holder.tagName.setOnClickListener(view -> {
openCloseView(holder.linearLayout);
});
holder.numberOfItems.setOnClickListener(view -> {
openCloseView(holder.linearLayout);
});
holder.linearLayout.addView(cardView);
}
}
private void openCloseView(View view) {
if (view.getVisibility() == View.GONE) {
view.setVisibility(View.VISIBLE);
boolean isVisible = view.getVisibility() == View.VISIBLE? true : false;
Log.d(TAG, ">>>View " + view +isVisible);
AnimationSet animation = new AnimationSet(true);
Animation animationAlpha = new AlphaAnimation(0, 1);
animation.addAnimation(animationAlpha);
Animation animationTranslate = new TranslateAnimation(0, 0, -view.getHeight(), 0);
animation.addAnimation(animationTranslate);
Animation animationY = new ScaleAnimation(1, 1, 0, 1);
animationY.setInterpolator(new LinearInterpolator());
animation.addAnimation(animationY);
animation.setDuration(200);
view.startAnimation(animation);
} else {
AnimationSet animation = new AnimationSet(true);
Animation animationAlpha = new AlphaAnimation(1, 0);
animation.addAnimation(animationAlpha);
Animation animationTranslate = new TranslateAnimation(0, 0, 0, -view.getHeight());
animation.addAnimation(animationTranslate);
Animation animationY = new ScaleAnimation(1, 1, 1, 0);
animationY.setInterpolator(new LinearInterpolator());
animation.addAnimation(animationY);
animation.setDuration(200);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
view.setVisibility(View.GONE);
boolean isVisible = view.getVisibility() == View.VISIBLE;
Log.d(TAG, ">>>View " + view +isVisible);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
view.startAnimation(animation);
}
}
只绑定屏幕上需要更新的项目。事实上,该组件会尽量减少 onbind 调用的次数,以防止额外的工作。没有承诺的调用顺序。因此,唯一一次 0 被确保被调用是在第一次加载时——即使在这种情况下它也不会被调用(例如,如果你正在进行反向填充并从底部开始)。如果您在编写代码时假设它总是尝试绑定 0,那么您就误解了 RecyclerView 的工作原理,需要重新评估您的设计。
为了解决我的问题,我使用 SharedPreferences 在视图是否可见时输入一个布尔值,然后在 onBindViewHolder()
中检索该数据并设置可见性。