我在工具栏中有一个 SearchView,位于 CardView 的 RecyclerView 列表上方。 SearchView 可以正确地根据文本输入过滤列表。但是,ListAdapter 中“onBindViewHolder()”方法中用于在每个 CardView 上使用 Color.GREEN 突出显示搜索文本的代码不起作用。
我设置了一个布尔值“isSearchMatched”,当 CardView 具有与 SearchView 文本匹配的文本时,该布尔值会切换为 true。 然后,我在 onBindViewHolder() 中使用“isSearchMatched”,加上带有新 ArrayList 的 SubmitList() 用于 ListAdapter 来识别对 CardView 项目的更改,以便可以突出显示 CardView 中的搜索文本...不走运。
我在这里缺少什么?
主要活动
mSearchView.setOnQueryTextListener() {
...
filter(newText)
}
private void filter(String searchText) {
ArrayList<Card> searchList = new ArrayList<>();
for (Card cardItem : mCards) {
if (cardItem.getTodo().toLowerCase().contains(searchText.toLowerCase(Locale.US))) {
searchList.add(cardItem);
**cardItem.setSearchMatched(true);**
}
}
if (!searchList.isEmpty()) {
adapter.setFilter(searchList, searchText);
}
Card.java // 模型项
@Entity(tableName = "cards_table")
public class Card implements Parcelable {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "cardId")
public int id;
@ColumnInfo(name = "cardTodo")
private String todo;
@ColumnInfo(name = "cardMatchedSearchText")
private boolean isSearchMatched = false;
...
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(id);
parcel.writeString(todo);
parcel.writeByte((byte) (isSearchMatched ? 1 : 0));
}
private void readFromParcel(Parcel in) {
id = in.readInt();
todo = in.readString();
isSearchMatched = in.readByte() != 0;
}
public int getId() {
return this.id;
}
public String getTodo() {
return this.todo;
}
public boolean isSearchMatched() {
return this.isSearchMatched;
}
public void setId(int id) {
this.id = id;
}
public void setTodo(String todo) {
this.todo = todo;
}
public void setSearchMatched(boolean isSearchMatched) {
this.isSearchMatched = isSearchMatched;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return Objects.equals(id, card.id) &&
Objects.equals(todo, card.todo) &&
Objects.equals(isSearchMatched, card.isSearchMatched);
}
@Override
public int hashCode() {
return Objects.hash(id, todo, isSearchMatched);
}
列表适配器
public class CardRVAdapter extends ListAdapter<Card, CardRVAdapter.ViewHolder> {
private String searchString = "";
public Spannable spannable;
private static final DiffUtil.ItemCallback<Card> DIFF_CALLBACK = new DiffUtil.ItemCallback<Card>() {
@Override
public boolean areItemsTheSame(Card oldItem, Card newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(Card oldItem, Card newItem) {
return oldItem.getTodo().equals(newItem.getTodo()) &&
oldItem.isSearchMatched() == (newItem.isSearchMatched());
}
};
public void setFilter(List<Card> newSearchList, String adapSearchText) {
if (newSearchList != null && !newSearchList.isEmpty()) {
this.searchString = adapSearchText.toLowerCase(Locale.US);
submitList(new ArrayList<>(newSearchList));
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView cardBlankText2; // displays text in the CardView and is matched against the user's search text input.
}
public ViewHolder(@NonNull final View itemView) {
super(itemView);
cardBlankText2 = itemView.findViewById(R.id.cardBlankText2);
}
void bindData(Card card, final int position) {
// Highlight matches from search characters is Green color.
if (searchString != null && !TextUtils.isEmpty(searchString)) {
String todoSearchHighlightFromVH = cardBlankText2.getText().toString().toLowerCase();
int offsetEnd2 = todoSearchHighlightFromVH.indexOf(searchString.toLowerCase(Locale.US));
final Spannable spannable2 = new SpannableString(cardBlankText2.getText());
spannable2.removeSpan(cardBlankText2);
cardBlankText2.setText(spannable2);
if (quickcard.isSearchMatched()) {
for (int start2 = 0; start2 < todoSearchHighlightFromVH.length() && offsetEnd2 != -1; start2 = offsetEnd2 + 1) {
offsetEnd2 = todoSearchHighlightFromVH.indexOf(searchString.toLowerCase(Locale.US), start2);
if (offsetEnd2 == -1) {
break;
} else {
final ForegroundColorSpan foregroundColorSpan2 = new ForegroundColorSpan(Color.GREEN);
spannable2.setSpan(foregroundColorSpan2, offsetEnd2, offsetEnd2 + searchString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
cardBlankText2.setText(spannable2);
}
}
}
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final Card card = getItem(position);
if (card != null) {
holder.bindData(card, position);
}
}
}
问题是
this.searchString = adapSearchText.toLowerCase(Locale.US);
ArrayList<Card> tempList = new ArrayList<>(newSearchList);
submitList(tempList);
它适用于从当前列表中删除项目,但对于回收器视图上的现有项目,它不会触发
onBindViewHolder
,因为项目的数据不会改变。要修复它,您应该添加 searchString
是 Card
模型的属性,当您过滤时,您应该使用新的搜索字符串创建新的 Card
模型