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