how do I highlight the searched text in my search filter?

有些话、适合烂在心里 提交于 2019-11-29 01:57:52

Let's assume you have create a custom adapter, then you can refer to the following code:

    @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;
    }

The mSearchText will be updated at the following inside performFiltering of ArrayFilter class.

String prefixString = prefix.toString().toLowerCase();
mSearchText = prefixString;

You can find more details in my sample code here or my GitHub (with lastest update).

Here is the screenshot

In your filter method, store the string used to perform the filter:

// Filter Class
public void filter(String searchString) {
    this.searchString = searchString;
    ...
    // Filtering stuff as normal.
}

You must declare a member string to store it:

public class ListViewAdapter extends BaseAdapter {
    ...    
    String searchString = "";
    ...

And, in getView you highlight the search term:

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);
    }
    ...
}

Hope it helps.

Hi on your adapter class ,make a spanneble text and set it to your textview, the below code you can use for reference.

 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);
    }

This is only demo for highlight text, you can implement your self by calling highlight(searchText, originalText) in filter,

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;
    }
 }
}

Put this code before setting text in 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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!