Frage AutoCompleteTextView-Adapter, "versteckter" Adapter?


Ich habe 3 AutoCompleteTextViews, und ich möchte 2 String [] Adapter auf ihnen registrieren. Momentan mache ich das:

atw_from.setAdapter(new ArrayAdapter(ctx, android.r.layout.simple_dropdown_item_1line, stages_adapter));

Nehmen wir an, mein Benutzer möchte "Középmező" eingeben, er fängt an, "Közé" einzugeben und er wird angeboten, Középmező zu wählen, bis es ganz einfach ist. Aber was ist, wenn der Benutzer zu faul ist, um Akzente zu schreiben (und viele von ihnen sind faul), so wird er nur Kozepmezo tippen, dann wird er kein Angebot bekommen, da es keinen Kozepmezo in meinem String [] gibt. Das was ich will ist, wenn er "Koze" eintippt, sollte ihm Középmező angeboten werden, also auch wenn er keine Akzente verwendet, wird ihm immer das eigentliche Wort mit den Akzenten angeboten.

Zur Zeit habe ich eine ziemlich dumme Lösung, ich habe eine String [] mit doppelter Größe des Originals [], die erste Hälfte enthält die Wörter mit Akzenten, die zweite enthält die deakzentuierten Versionen. So, jetzt, wenn er Közé eintippt, wird ihm Középmező angeboten, und wenn er Koze tippt, wird ihm Kozepmezo angeboten. Es funktioniert, weil der Server beide Versionen verarbeiten kann, aber es sieht einfach albern aus, und ich möchte es lösen.

Von dem, was ich verstehe, sollte ich einen vollständigen benutzerdefinierten Adapter machen. Ist das der beste Ansatz oder ist eine Lösung im SDK enthalten? Wenn ich den benutzerdefinierten Adapter machen sollte, könnte mir dann jemand in die richtige Richtung zeigen, wie das geht? :)

EDIT: fügte meine eigene Antwort hinzu, sollte für jeden arbeiten, Prost für die andere Antwort, die mich in die gute Richtung gelenkt hat!


5
2018-03-11 19:47


Ursprung


Antworten:


Okey, nach einer Menge Schmerzen im Umgang damit, hier ist das, was ich am Ende getan habe. Dies ist überhaupt keine gute Übung, und ich mag es falsch machen, aber zumindest funktioniert es jetzt perfekt.

Einfach Strg + C, Strg + V den Quellcode von Basisadapter, und Strg + C, Strg + v der Quellcode von ArrayAdapter. Betrachten Sie nun die private innere Klasse ArrayFilter, insbesondere die performFiltering-Methode. Ändern Sie (nicht überschreiben!) Es, so viel wie Sie wollen, in meinem Fall fügte ich eine Menge .replace ("x", "y") Dings, für den deaccenting Teil hinzu.

Was auch immer ich versuchte, entweder produzierte unvorhersehbare Kraft schließt (viel, und völlig zufällig), oder ich konnte es einfach nicht tun, da zu viele Methoden / Variablen privat sind, anstatt geschützt. Ich muss sagen, Google sollte diese Codes erneut lesen ...

Hinweis: Sie müssen nicht unbedingt Strg + C Strg + v die BaseAdapter-Codes, da es eine öffentliche abstrakte Klasse ist, aber hey, es ist nicht so viel von einem Code, und auf diese Weise ist alles da, deutlich sichtbar für Sie .

Prost


1
2018-04-10 09:26



Ich würde tatsächlich für einen kundenspezifischen Adapter gehen, in dem Sie Ihre eigene Filterfunktion zur Verfügung stellen, um auf den Akzent- und deaccentated Anmerkungen zusammenzubringen.

Eine Beispielimplementierung, die genau das tut, kann gefunden werden Hier. Grundsätzlich müssen Sie die eigentliche Filterung implementieren performFiltering - Ich gehe davon aus, dass Sie bereits eine Möglichkeit haben, die Abfragen zu deaktivieren, da Sie gerade Ihren String[] mit deakzenten Versionen. Sie werden die Abfrage mit und ohne Akzente gegen die Einträge in Ihrem Array vergleichen wollen (die Sie mit und ohne Akzente verwenden möchten). Am Ende sollten Sie mindestens die folgenden vier Tests haben:

accented(query) -> accented(entry)
accented(query) -> deaccented(entry)
deaccented(query) -> accented(entry)
deaccented(query) -> deaccented(entry)

Indem Sie die Wörter spontan deaktivieren, müssen Sie nur die String[] mit akzentuierten Wörtern, während die Filterlogik (in Ihrem Adapter) für die Übereinstimmung mit (de) akzentuierten Wörtern sorgt.

Bearbeiten: wie besprochen, unten eine Beispielimplementierung in einem meiner laufenden Projekte.

Einige Hinweise:

  1. CustomArrayAdapter ist meist eine Wrapper-Klasse, die gängige Aufgaben vereinfacht; z.B. Interaktion mit einem Zeilenwrapper / Ansichtshalter. Im Grunde braucht es nur einen Konstruktor und eine Implementierung von updateRow (die offensichtlich von der Superklasse aufgerufen wird ' getView Methode).
  2. CustomRowWrapper sollte ziemlich einfach sein.
  3. ArrayUtil und ArrayUtil.FilterFuction Achten Sie auf die eigentliche Filterung. Einfach ausgedrückt, dienen diese als Ersatz für eine for-Schleife, die eine neue Liste aller Elemente erstellt, die bestimmten Kriterien entsprechen.

public class CARMedicationSuggestionAdapter extends CustomArrayAdapter<CARMedicationInfo, RowWrapper> {

    private List<CARMedicationInfo> mMedications;
    private Filter mFilter;

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     * constructor
     * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    public CARMedicationSuggestionAdapter(Context context, List<CARMedicationInfo> objects) {
        super(RowWrapper.class, context, R.layout.medication_suggestion_item_layout, objects);
        // keep copy of all items for lookups 
        mMedications = new ArrayList<CARMedicationInfo>(objects);
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     * update row
     * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    @Override protected void updateRow(RowWrapper wrapper, CARMedicationInfo item) {
        wrapper.getNameTextView().setText(item.toString());
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     * get filter
     * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    @Override public Filter getFilter() {
        // return if already created
        if (mFilter != null) return mFilter;
        mFilter = new Filter() {
            @Override protected void publishResults(CharSequence constraint, FilterResults results) {
                @SuppressWarnings("unchecked") List<CARMedicationInfo> filtered = (List<CARMedicationInfo>) results.values;
                if (results == null || results.count == 0) return;
                // clear out current suggestions and add all new ones
                clear(); 
                addAll(filtered);
            }

            @Override protected FilterResults performFiltering(final CharSequence constraint) {
                // return empty results for 'null' constraint
                if (constraint == null) return new FilterResults();
                // get all medications that contain the constraint in drug name, trade name or whose string representation start with the constraint
                List<CARMedicationInfo> suggestions = ArrayUtil.filter(mMedications, new ArrayUtil.FilterFunction<CARMedicationInfo>() {
                    @Override public boolean filter(CARMedicationInfo item) {
                        String query = constraint.toString().toLowerCase().trim();
                        return  item.mMedicationDrugName.toLowerCase().contains(query) || 
                                item.mMedicationTradeName.toLowerCase().contains(query) ||
                                item.toString().toLowerCase().startsWith(query); 
                    }
                });
                // set results and size
                FilterResults filterResults = new FilterResults();
                filterResults.values = suggestions;
                filterResults.count = suggestions.size();
                return filterResults;
            }
        };
        return mFilter;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     * row wrapper
     * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    static class RowWrapper extends CustomRowWrapper {

        private ImageView mIconImageView;
        private TextView mNameTextView;

        public RowWrapper(View row) {
            super(row);
        }

        public ImageView getIconImageView() {
            if (mIconImageView == null) mIconImageView = (ImageView) mRow.findViewById(R.id.icon_imageview);
            return mIconImageView;
        }

        public TextView getNameTextView() {
            if (mNameTextView == null) mNameTextView = (TextView) mRow.findViewById(R.id.name_textview);
            return mNameTextView;
        }

    }

}

1
2018-04-04 19:38



Schau dir diesen Thread an Entfernen-Akzente-von-String und Android Normalisierer Klasse

[BEARBEITEN] oder du könntest es versuchen Merge-Adapter mit beiden Arrays


0
2018-04-01 14:03