¿Cómo resalto el texto buscado en mi filtro de búsqueda?
Estoy intentando hacer una búsqueda tal que todas las letras "visibles" de la búsqueda se deben destacar. Intenté usar spannable pero eso no hizo el truco, quizás no lo hice derecho? Basado en esto: Resalte el texto buscado en los elementos ListView ¿Cómo puedo resaltar el texto visible? Aquí está mi filtro:
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!
Aquí está mi getview
- Dibujar línea a través de texto en textview
- Adición dinámica de una vista de texto
- Dos estilos diferentes en un solo textview con diversa gravedad y hieght
- Android Hello GridView Tutorial no mostrará imágenes
- Barra de acción de corte / copia personalizada para EditText que muestra las manijas de selección de texto
@Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; ViewHolder holder; if(filtering && m_filterList != null && m_filterList.size() > position) position = m_filterList.get(position); if (rowView == null) { holder = new ViewHolder(); mInflater = context.getLayoutInflater(); rowView = mInflater.inflate(R.layout.rowlayout, null); // configure view holder holder.text = (TextView) rowView.findViewById(R.id.label); holder.text.setTextColor(Color.WHITE); holder.text.setSingleLine(); holder.text.setTextSize(15); holder.text.setEllipsize(TextUtils.TruncateAt.END); holder.text.setPadding(2, 2, 6, 2); Typeface label = Typeface.createFromAsset(holder.text.getContext().getAssets(), "fonts/arial-bold.ttf"); holder.text.setTypeface(label); holder.image = (ImageView) rowView.findViewById(R.id.icon); holder.image.setPadding(6, 4, 0, 4); holder.image.getLayoutParams().height = (int) getResources().getDimension(R.dimen.icon_width_height); holder.image.getLayoutParams().width = (int) getResources().getDimension(R.dimen.icon_width_height); rowView.setBackgroundResource(R.drawable.row_border); rowView.setPadding(2, 2, 6, 2); rowView.setTag(holder); }else { // fill data holder = (ViewHolder) rowView.getTag(); } String id = listItemsHolder.getid(position); String name = listItemsHolder.getName(position); holder.image.setVisibility(View.VISIBLE); if (name != null) { holder.text.setText(listItemsHolder.getName(position)); ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) holder.text.getLayoutParams(); params.leftMargin = 20; }else{ holder.text.setText(id); } String fullText = listItemsHolder.getName(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); holder.text.setText(spannable); } else { holder.text.setText(fullText); } } else { holder.text.setText(fullText); } return rowView; }
- Implementar un TextView personalizado con textSize personalizado
- Android - problema con desplazamiento automático en TextView
- Cómo alinear un elemento a la derecha de su centro de padres? (Diseños de Android)
- Fondo de desvanecimiento de TextView desplazable
- Android OS bug con algunos dispositivos que ejecutan Jelly Bean / 4.2.1 - TextView.setError (error CharSequence) Icono que falta
- Autolink dentro de un TextView en android
- Texto intermitente en la vista android
- Uso de Textview personalizado en estilo
Supongamos que tiene crear un adaptador personalizado, a continuación, puede consultar el código siguiente:
@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; }
El mSearchText
se actualizará en la siguiente performFiltering
dentro de performFiltering
de ArrayFilter
.
String prefixString = prefix.toString().toLowerCase(); mSearchText = prefixString;
Puede encontrar más detalles en mi código de ejemplo aquí o en mi GitHub (con la última actualización) .
Aquí está la captura de pantalla
En su método de filtro , almacene la cadena utilizada para realizar el filtro:
// Filter Class public void filter(String searchString) { this.searchString = searchString; ... // Filtering stuff as normal. }
Debe declarar una cadena de miembro para almacenarla:
public class ListViewAdapter extends BaseAdapter { ... String searchString = ""; ...
Y, en getView resalta el término de búsqueda:
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); } ... }
Espero eso ayude.
Esto es sólo demo para resaltar texto, puede implementar su auto llamando a highlight(searchText, originalText)
en el filtro,
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; } } }
Ponga este código antes de establecer el texto en 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);
Hola en tu clase del adaptador, haces un texto del spanneble y lo fijas a tu textview, el código abajo que puedes utilizar para la referencia.
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); }
- Cómo hacer que el primer carácter sea mucho más grande que otro en un TextView
- Posible obtener detalles de error específicos de Android SQLiteConstraintException?