Android 如何在搜索筛选器中突出显示搜索的文本?

Android 如何在搜索筛选器中突出显示搜索的文本?,android,android-layout,android-fragments,textview,android-search,Android,Android Layout,Android Fragments,Textview,Android Search,我正在尝试进行搜索,以便突出显示所有“可见”搜索字母。我试着使用Spanable,但没有奏效,也许我做得不对?基于此: 如何突出显示可见文本?这是我的过滤器: private LayoutInflater mInflater; private ValueFilter valueFilter; public MySimpleArrayAdapter(Activity context) { this.context = context;

我正在尝试进行搜索,以便突出显示所有“可见”搜索字母。我试着使用Spanable,但没有奏效,也许我做得不对?基于此: 如何突出显示可见文本?这是我的过滤器:

private LayoutInflater mInflater;

        private ValueFilter valueFilter;

        public MySimpleArrayAdapter(Activity context) {

            this.context = context;
            mInflater = LayoutInflater.from(context);

        }
        private class ValueFilter extends Filter {


            //Invoked in a worker thread to filter the data according to the constraint.
            @Override
            protected synchronized FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();

                if (constraint != null && constraint.length() > 0) {

                    ArrayList<Integer> filterList = new ArrayList<>();

                    int iCnt = listItemsHolder.Names.size();
                    for (int i = 0; i < iCnt; i++) {
                        if(listItemsHolder.Types.get(i).toString().indexOf("HEADER_")>-1){
                            continue;
                        }
                        if (listItemsHolder.Names.get(i).matches(getRegEx(constraint))||(listItemsHolder.Names.get(i).toLowerCase().contains(constraint.toString().toLowerCase()))) {
                            if(filterList.contains(i))
                                continue;

                            filterList.add(i);

                        }
                        }

                    results.count = filterList.size();

                    results.values = filterList;
                }else {
                String prefixString = getRegEx(constraint);
                mSearchText = prefixString;
                    results.count = listItemsHolder.Names.size();

                    ArrayList<Integer> tList = new ArrayList<>();
                    for(int i=0;i<results.count;i++){
                        tList.add(i);
                    }

                    results.values = tList;

                }

                return results;


}


                //Invoked in the UI thread to publish the filtering results in the user interface.
                @SuppressWarnings("unchecked")
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
                    ArrayList<Integer> resultsList = (ArrayList<Integer>)results.values;
                    if(resultsList != null) {
                        m_filterList = resultsList;
                    }
                    notifyDataSetChanged();
                }

            }

            public String getRegEx(CharSequence elements){
                String result = "(?i).*";
                for(String element : elements.toString().split("\\s")){
                    result += element + ".*";
                }
                result += ".*";
                return result;
            }

Thanks in advance! 

这是突出显示文本的唯一演示,您可以通过调用
在过滤器中突出显示(searchText,originalText)

public class MainActivity extends AppCompatActivity {
EditText editText;
TextView text;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editText = (EditText) findViewById(R.id.editText);
    text = (TextView) findViewById(R.id.textView1);

    editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
                text.setText(highlight(editText.getText().toString(), text.getText().toString()));
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });

}

public static CharSequence highlight(String search, String originalText) {
    String normalizedText = Normalizer.normalize(originalText, Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "").toLowerCase();
    int start = normalizedText.indexOf(search);
    if (start <= 0) {
        return originalText;
    } else {
        Spannable highlighted = new SpannableString(originalText);
        while (start > 0) {
            int spanStart = Math.min(start, originalText.length());
            int spanEnd = Math.min(start + search.length(), originalText.length());
            highlighted.setSpan(new BackgroundColorSpan(Color.YELLOW), spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            start = normalizedText.indexOf(search, spanEnd);
        }
        return highlighted;
    }
 }
}
public类MainActivity扩展了AppCompatActivity{
编辑文本编辑文本;
文本查看文本;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=(editText)findViewById(R.id.editText);
text=(TextView)findViewById(R.id.textView1);
editText.addTextChangedListener(新的TextWatcher(){
@凌驾
更改前文本之前的公共void(字符序列s、int start、int count、int after){
}
@凌驾
public void onTextChanged(字符序列、int start、int before、int count){
text.setText(高亮显示(editText.getText().toString(),text.getText().toString());
}
@凌驾
公共无效后文本已更改(可编辑){
}
});
}
公共静态字符序列高亮显示(字符串搜索、字符串原始文本){
字符串normalizedText=Normalizer.normalize(originalText,Normalizer.Form.NFD).replaceAll(\\p{incombindingDiacriticalMarks}+,“”)。toLowerCase();
int start=normalizedText.indexOf(搜索);
如果(从0开始){
int spanStart=Math.min(start,originalText.length());
int spanEnd=Math.min(start+search.length(),originalText.length());
突出显示.setSpan(新背景色SPAN(颜色.黄色)、SPAN开始、SPAN结束、SPAN可启用.SPAN_独占性SPAN_独占性);
开始=normalizedText.indexOf(搜索,结束);
}
返回突出显示;
}
}
}

在getview中设置文本之前先输入此代码

Spannable wordtoSpan = new SpannableString("Your_text_in_getviews");

        wordtoSpan.setSpan(new ForegroundColorSpan(Color.RED), 0, edtFilter
                .getText().toString().length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txt_contact.setText(wordtoSpan);

您好,在适配器类上,创建一个可跨越文本并将其设置为textview,下面的代码可供参考

 if ("text contains filter value".toLowerCase().contains("filter".toLowerCase())) {
        Spannable spanText = Spannable.Factory.getInstance().newSpannable("text contains filter value".toLowerCase());

        Matcher matcher = Pattern.compile("filter".toLowerCase())
                .matcher("text contains filter value".toLowerCase());
        while (matcher.find()) {
            spanText.setSpan(new ForegroundColorSpan(Color.RED), matcher.start(),
                    matcher.start() + "filter".length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
       yourTextView.setText(spanText);
    }

筛选方法中,存储用于执行筛选的字符串:

// Filter Class
public void filter(String searchString) {
    this.searchString = searchString;
    ...
    // Filtering stuff as normal.
}
您必须声明一个成员字符串来存储它:

public class ListViewAdapter extends BaseAdapter {
    ...    
    String searchString = "";
    ...
并且,在getView中突出显示搜索词:

public View getView(final int position, View view, ViewGroup parent) {
    ...
    // Set the results into TextViews
    WorldPopulation item = worldpopulationlist.get(position);
    holder.rank.setText(item.getRank());
    holder.country.setText(item.getCountry());
    holder.population.setText(item.getPopulation());

    // Find charText in wp
    String country = item.getCountry().toLowerCase(Locale.getDefault());
    if (country.contains(searchString)) {
        Log.e("test", country + " contains: " + searchString);
        int startPos = country.indexOf(searchString);
        int endPos = startPos + searchString.length();

        Spannable spanText = Spannable.Factory.getInstance().newSpannable(holder.country.getText()); // <- EDITED: Use the original string, as `country` has been converted to lowercase.
        spanText.setSpan(new ForegroundColorSpan(Color.RED), startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        holder.country.setText(spanText, TextView.BufferType.SPANNABLE);
    }
    ...
}
public View getView(最终int位置、视图视图、视图组父视图){
...
//将结果设置为文本视图
WorldPopulation项=worldpopulationlist.get(位置);
holder.rank.setText(item.getRank());
holder.country.setText(item.getCountry());
holder.population.setText(item.getPopulation());
//在wp中查找图表文本
字符串country=item.getCountry().toLowerCase(Locale.getDefault());
if(country.contains(searchString)){
Log.e(“测试”,国家+”包含:“+搜索字符串);
int startPos=country.indexOf(searchString);
int endPos=startPos+searchString.length();

Spannable spanText=Spannable.Factory.getInstance().newspanable(holder.country.getText());//假设您已经创建了一个自定义适配器,那么您可以参考以下代码:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        TextView text;

        if (convertView == null) {
            view = mInflater.inflate(mResource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (mFieldId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = (TextView) view.findViewById(mFieldId);
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }
        String item = getItem(position);
        text.setText(item);

        String fullText = getItem(position);
        // highlight search text
        if (mSearchText != null && !mSearchText.isEmpty()) {
            int startPos = fullText.toLowerCase(Locale.US).indexOf(mSearchText.toLowerCase(Locale.US));
            int endPos = startPos + mSearchText.length();

            if (startPos != -1) {
                Spannable spannable = new SpannableString(fullText);
                ColorStateList blueColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{Color.BLUE});
                TextAppearanceSpan highlightSpan = new TextAppearanceSpan(null, Typeface.BOLD, -1, blueColor, null);
                spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                text.setText(spannable);
            } else {
                text.setText(fullText);
            }
        } else {
            text.setText(fullText);
        }

        return view;
    }
mSearchText
将在
ArrayFilter
类的
performFiltering
内部更新

String prefixString = prefix.toString().toLowerCase();
mSearchText = prefixString;
您可以在或中找到更多详细信息

这是截图


可以用更简单的方法完成:

  • 定义自定义适配器:
  • class HighlightAutoCompleteAdapter(上下文:上下文,资源:Int,私有val textResId:Int,项:列表):
    ArrayAdapter(上下文、资源、textResId、项){
    private val inflater=LayoutInflater.from(上下文)
    var queryText=“”
    覆盖视图(位置:Int,convertView:View?,父级:ViewGroup):视图{
    val view=convertView?:充气机。充气(textResId,父项,false)
    val textView:textView=view.findViewById(android.R.id.text1)作为textView
    val fullText=getItem(位置)作为字符串
    //突出显示搜索文本
    val突出显示:Spannable=SpannableString(全文)
    if(queryText.isNotEmpty()){
    val startPos:Int=fullText.toLowerCase(Locale.US).indexOf(queryText.toLowerCase(Locale.US))
    val endPos:Int=startPos+queryText.length
    如果(startPos!=-1){
    突出显示设置跨距(样式跨距(粗体),
    startPos,
    endPos,
    SPAN可启用。SPAN_独占(仅限)
    }
    }
    textView.text=高亮显示
    返回视图
    }
    }
    
  • 创建适配器并侦听文本更改以保持适配器更新:
  • val searchEditText:AutoCompleteTextView=view.findViewById(R.id.search\u edit\u text)
    val arrayAdapter=HighlightAutoCompleteTadapter(requireContext(),0,R.layout.search\u complete\u项目,autoCompletionList)
    searchEditText.setAdapter(arrayAdapter)
    searchEditText.addTextChangedListener(对象:TextWatcher{
    重写fun beforeTextChanged(s:CharSequence?,start:Int,count:Int,after:Int){}
    重写已更改的文本(s:CharSequence?,start:Int,before:Int,count:Int){
    arrayAdapter.queryText=s?.toString()?:“”
    }
    覆盖后文本更改(s:可编辑?{}
    })
    
    这冻结了键盘,还有其他方法吗感谢详细的答案。我将尝试突出显示逻辑并让您知道。现在,感谢您采取额外的步骤,正因为如此,奖金是您的。如果它对我有效,我将勾选此答案作为正确答案。是的,我忘记重置
    mSearchText
    variable,在我的代码中,
    mSearchText=“”;
    应该在
    if(prefix==null | | | prefix.length()==0){
    中。我刚刚将我的示例项目发布到
    String prefixString = prefix.toString().toLowerCase();
    mSearchText = prefixString;