Android:使用 RecyclerView 和 ListAdapter 修复 ForegroundColorSpan 搜索文本突出显示

问题描述 投票:0回答:1

我在工具栏中有一个 SearchView,它位于 CardView 的 RecyclerView 列表上方。 SearchView 可以正确地根据文本输入过滤列表。但是,ListAdapter 中 onBindViewHolder() 方法中使用 Color.GREEN 突出显示搜索文本的代码无法正常工作。

垂直 RecyclerView 列表中返回的第一个 CardView 永远不会突出显示搜索文本。 然后,其下方多次带有搜索文本的其他 CardView 也始终不突出显示。 此外,向下滚动列表然后返回到列表顶部将突出显示找到的一些搜索文本,而首次返回 RecyclerView 列表时该文本不会突出显示。

也许问题在于使用 ListAdapter 作为适配器,因为视图在后台线程上更新并且数据集尚未准备好? 关于如何在垂直滚动的 RecyclerView 中使用 ListAdapter 正确突出显示搜索文本有什么想法吗?

MainActivity
....  
public boolean onCreateOptionsMenu(Menu menu) {

    mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            filter(newText); 
            return false;
        }
    }); 
} 

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);
        }
    }  
    if (!searchList.isEmpty()) {  
        adapter.setFilter(searchList, searchText);
}

ListAdapter

public class CardRVAdapter extends ListAdapter<Card, CardRVAdapter.ViewHolder> {
....
    private String searchString = "";
    public Spannable spannable;
    
    public void setFilter(List<Card> newSearchList, String adapSearchText) {

        if (newSearchList != null && !newSearchList.isEmpty()) {
            this.searchString = adapSearchText.toLowerCase(Locale.US);
            ArrayList<Card> tempList = new ArrayList<>(newSearchList); 
            submitList(tempList);
        }
    }
  
    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView cardBlankText2;  // displays text in the CardView and is matched against the search text input.
        ForegroundColorSpan fcs = new ForegroundColorSpan(Color.GREEN);

        public ForegroundColorSpan getFCS() {
            return fcs;
        }
    }

    public ViewHolder(@NonNull final View itemView) {
        super(itemView);
         
        cardBlankText2 = itemView.findViewById(R.id.cardBlankText2);
    }

    void bindData(Card card, final int position) {

        spannable = Spannable.Factory.getInstance().newSpannable(cardBlankText2.getText().toString());

        // Get any previous spans and remove them
        ForegroundColorSpan[] foregroundSpans = spannable.getSpans(0,spannable.length(), ForegroundColorSpan.class);

        // Highlight matches from search characters is Green color.
        if (searchString != null && !TextUtils.isEmpty(searchString)) {

            for (ForegroundColorSpan span : foregroundSpans) {
                spannable.removeSpan(span);
            } 
           
            int index = spannable.toString().toLowerCase(Locale.US).indexOf(searchString);    
            while (index != -1) {
                spannable.setSpan(getFCS(), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                index = spannable.toString().indexOf(searchString,index + searchString.length());
            }
            cardBlankText2.setText(spannable, TextView.BufferType.SPANNABLE);
        }    
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        
        final Card card = getCardAt(position);
        if (card != null) {        
            holder.bindData(card, position);
        }
    }

    public Card getCardAt(int position) {
        return getItem(position);
    }    

}   
for-loop android-recyclerview searchview spannable android-listadapter
1个回答
0
投票

问题是

            this.searchString = adapSearchText.toLowerCase(Locale.US);
            ArrayList<Card> tempList = new ArrayList<>(newSearchList); 
            submitList(tempList);

它适用于从当前列表中删除项目,但对于回收器视图上的现有项目,它不会触发

onBindViewHolder
,因为项目的数据不会改变。要修复它,您应该添加
searchString
Card
模型的属性,当您过滤时,您应该使用新的 `
 创建新的 
Card

模型
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.