¿Cómo puedo permitir buscar en Android que funciona con carácter acentos aswell?

Angela Heely:

He implementado un mecanismo de búsqueda en mi aplicación, de manera que cuando la búsqueda de un nombre o correo electrónico, que muestra la cadena con el carácter correspondiente. Sin embargo, existe una serie de acentuados en mi lista y cuando lo busco con un personaje regular correspondiente a esa específica acento, por ejemplo si tengo cadena "Angela" y buscar "Angela" es imposible mostrar la cadena menos que busco con la cadena exacta " Angela".

Estoy tratando de conseguir que funcione independientemente del acento o no, por ejemplo, si el tipo i en "a", debe mostrar todas las cadenas que contengan "A" y "a" y viceversa. ¿Alguna idea de cómo hacer esto? Busqué un montón de artículos en línea, por ejemplo: ¿Cómo ignorar el acento en SQLite consulta (Android) "y trató normalizador también, pero funciona parcialmente, si la búsqueda 'a', sí muestra las letras acentuadas con letras regulares aswell pero si la búsqueda con las letras acentuadas, duerma muestra nada.

Aquí está mi código de filtro:

 @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
                    mSearchGuestListResponseListFiltered = mSearchGuestListResponseList;
                } else {
                    List<RegisterGuestList.Guest> filteredList = new ArrayList<>();
                    for (RegisterGuestList.Guest row : mSearchGuestListResponseList) {

                        // name match condition. this might differ depending on your requirement
                        // here we are looking for name or phone number match
                        String firstName = row.getGuestFirstName().toLowerCase();
                        String lastName = row.getGuestLastName().toLowerCase();
                        String name = firstName + " " +lastName;
                        String email = row.getGuestEmail().toLowerCase();
                        if ( name.trim().contains(charString.toLowerCase().trim()) ||
                                email.trim().contains(charString.toLowerCase().trim())){
                            filteredList.add(row);
                            searchText = charString.toLowerCase();
                        }
                    }

                    mSearchGuestListResponseListFiltered = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = mSearchGuestListResponseListFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                mSearchGuestListResponseListFiltered = (ArrayList<RegisterGuestList.Guest>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }

Aquí está toda la clase adaptador si alguien está interesado: https://pastebin.com/VxsWWMiS Aquí está la vista de la actividad correspondiente:

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                mSearchGuestListAdapter.getFilter().filter(query);

                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                mSearchGuestListAdapter.getFilter().filter(newText);
                mSearchGuestListAdapter.notifyDataSetChanged();
                mSearchGuestListAdapter.setFilter(newText);

                if(mSearchGuestListAdapter.getItemCount() == 0){


                    String sourceString = "No match found for <b>" + newText + "</b> ";
                    mNoMatchTextView.setText(Html.fromHtml(sourceString));
                } else {
                    mEmptyRelativeLayout.setVisibility(View.GONE);
                    mRecyclerView.setVisibility(View.VISIBLE);
                }
                return false;
            }
        });

Feliz de compartir los detalles si es necesario. También, al azar me pongo la indexoutofboundexception onBind () Método mientras que la búsqueda (uso recyclerview para la lista):

java.lang.IndexOutOfBoundsException: Index: 7, Size: 0
        at java.util.ArrayList.get(ArrayList.java:437)

¿Alguna idea de cómo hacer esto?

P. I:

En general, yo recomendaría usar una Collatorcon un ajuste de la fuerza Collator.PRIMARYpara comparar cadenas que contienen acentos y casos variadas (por ejemplo, Nfrente ny écontra e). Por desgracia, Collatorno tiene una contains()función.

Así que vamos a hacer nuestro propio.

private static boolean contains(String source, String target) {
    if (target.length() > source.length()) {
        return false;
    }

    Collator collator = Collator.getInstance();
    collator.setStrength(Collator.PRIMARY);

    int end = source.length() - target.length() + 1;

    for (int i = 0; i < end; i++) {
        String sourceSubstring = source.substring(i, i + target.length());

        if (collator.compare(sourceSubstring, target) == 0) {
            return true;
        }
    }

    return false;
}

Este itera sobre la cadena de origen, y comprueba si cada subcadena con la misma longitud que el destino de búsqueda es igual a la objetivo de búsqueda, por lo que se refiere a la alzadora.

Por ejemplo, imaginemos nuestra cadena de origen es "This is a Tèst"y estamos buscando la palabra "test". Este método va a iterar sobre cada cuatro letras subcadena:

This
his 
is i
s is
 is 
is a
s a 
 a T
a Tè
 Tès
Tèst

Y volverá verdadera tan pronto como se encuentra una coincidencia. Dado que la fuerza se establece en Collator.PRIMARY, la alzadora considera "Tèst"y "test"el ser igual, y así nuestros devuelve el método true.

Es muy posible que hay son más optimizaciones que deben introducirse en este método, pero esto debe ser un punto de partida razonable.

Editar : Una posible la optimización es teclas intercalación de apalancamiento, así como los detalles conocidos de la implementación de RuleBasedCollatory RuleBasedCollationKey(suponiendo que tiene la guayaba de Google en su proyecto):

private static boolean containsBytes(String source, String target) {
    Collator collator = Collator.getInstance();
    collator.setStrength(Collator.PRIMARY);

    byte[] sourceBytes = dropLastFour(collator.getCollationKey(source).toByteArray());
    byte[] targetBytes = dropLastFour(collator.getCollationKey(target).toByteArray());

    return Bytes.indexOf(sourceBytes, targetBytes) >= 0;
}

private static byte[] dropLastFour(byte[] in) {
    return Arrays.copyOf(in, in.length - 4);
}

Esto es considerablemente más frágil (probablemente no funciona para todos los locales), pero en mis pruebas es en algún lugar entre 2x y 10x más rápido.

Editar : Para el apoyo destacando, debe convertir contains()a indexOf(), y luego usar esa información:

private static int indexOf(String source, String target) {
    if (target.length() > source.length()) {
        return -1;
    }

    Collator collator = Collator.getInstance();
    collator.setStrength(Collator.PRIMARY);

    int end = source.length() - target.length() + 1;

    for (int i = 0; i < end; i++) {
        String sourceSubstring = source.substring(i, i + target.length());

        if (collator.compare(sourceSubstring, target) == 0) {
            return i;
        }
    }

    return -1;
}

Y entonces se podría aplicar de esta manera:

String guestWholeName = guest.getGuestFirstName() + " " + guest.getGuestLastName();
int wholeNameIndex = indexOf(guestWholeName, searchText);

if (wholeNameIndex > -1) {
    Timber.d("guest name first : guest.getGuestFirstName() %s", guest.getGuestFirstName());
    Timber.d("guest name last : guest.getGuestLastName() %s", guest.getGuestLastName());

    int endPos = wholeNameIndex + searchText.length();

    Spannable spannable = new SpannableString(guestWholeName);
    Typeface firstNameFont = Typeface.createFromAsset(context.getAssets(), "fonts/Graphik-Semibold.otf");
    spannable.setSpan(new CustomTypefaceSpan("", firstNameFont), wholeNameIndex, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Objects.requireNonNull(guestName).setText(spannable);
} else {
    Objects.requireNonNull(guestName).setText(guestWholeName);
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=330852&siteId=1
Recomendado
Clasificación