2012-03-11 18 views
5

Ho 3 AutoCompleteTextViews e vorrei registrare 2 adattatori String [] su di essi. Attualmente, sto facendo questo:Adattatore AutoCompleteTextView, adattatore "nascosto"?

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

Diciamo che il mio utente vuole digitare "Középmező", inizia a digitare "koze" e sarà offerto di scegliere Középmező, fino a questo, è abbastanza semplice. Ma cosa succede se l'utente è troppo pigro per digitare accenti (e molti di loro sono pigri), quindi scriverà solo Kozepmezo, quindi non otterrà alcuna offerta, poiché non c'è Kozepmezo nella mia stringa []. La cosa che voglio è, se digita in "Koze", dovrebbe essere offerto a Középmező, quindi anche se non usa accenti, gli verrà sempre offerta la parola vera con gli accenti.

Attualmente, ho una soluzione piuttosto stupida, ho una stringa [] con il doppio della dimensione dell'originale [], la prima metà contiene le parole con accenti, la seconda contiene le versioni non implementate. Così ora, se batte Közé, gli verrà offerto Középmező, e se lui usa Koze, gli verrà offerto Kozepmezo. Funziona perché il server può elaborare entrambe le versioni, ma sembra semplicemente stupido, e io voglio risolverlo.

Da quello che ho capito, dovrei creare un adattatore completamente personalizzato. È l'approccio migliore o c'è qualche soluzione inclusa nell'SDK? Se dovessi creare l'adattatore personalizzato, qualcuno potrebbe indicarmi la giusta direzione, su come farlo? :)

EDIT: aggiunta la mia risposta, dovrebbe funzionare per tutti, applausi per l'altra risposta, che mi ha indirizzato verso la buona direzione!

risposta

1

Okey, dopo un sacco di dolore nel culo che fare con questo, ecco la cosa che ho fatto alla fine. Questa NON è affatto una buona pratica e potrei sbagliarmi, ma almeno adesso funziona perfettamente.

Semplicemente ctrl + c, ctrl + v il codice sorgente di BaseAdapter e ctrl + c, ctrl + v il codice sorgente di ArrayAdapter. Ora guarda la classe interna privata, ArrayFilter, in particolare il metodo performFiltering. Modifica (non scavalcare!), Per quanto tu voglia, nel mio caso ho aggiunto un sacco di cose .replace ("x", "y"), per la parte di deaccenting.

Qualsiasi altra cosa provassi, o produceva chiusure di forze imprevedibili (molto, e completamente casuali), o semplicemente non potevo farlo, dato che troppi metodi/variabili sono privati, invece che protetti. Devo dire, Google dovrebbe rivisitare i codici ...

Nota: non è necessario ctrl + c ctrl + v i codici BaseAdapter, poiché è una classe astratta pubblica, ma hey, non è così gran parte di un codice, e in questo modo tutto è lì, chiaramente visibile per te.

applausi

+0

Peccato sentirti weren Sono in grado di risolvere il tuo problema con la mia soluzione precedente. Se sei (ancora) interessato, potrei pubblicare la soluzione che ho scritto un paio di settimane fa? Utilizziamo una libreria interna per semplificare le attività comuni, ma la parte filtrante dovrebbe essere relativamente intatta. –

+0

Sono sempre interessato a soluzioni migliori! :) Se non ti dispiace, darei un'occhiata su di esso. Ad ogni modo, la tua risposta mi ha indirizzato nella direzione, il che mi ha fatto risolvere il mio problema, quindi un grande thx già per te. Inoltre, stavo pensando di riscrivere completamente alcune parti di questo ArrayAdapter, dato che, in generale, potrebbe essere stabile, ma nel mio caso non avrà bisogno di alcuni array aggiuntivi, riducendo così la memoria/tempo di CPU del filtro necessario. – hundeva

+0

OK, ho aggiunto un codice che sto attualmente utilizzando in uno dei miei progetti alla mia risposta precedente. Il bit più interessante per te sarebbe il metodo 'getFilter' sovrascritto. Spero che abbia senso per te. :) –

1

Vorrei davvero andare per un adattatore personalizzato, in cui è fornire il proprio funzione di filtro da abbinare sia alle notazioni accentate che a quelle meno accentuate.

Un'implementazione di esempio che fa proprio questo, può essere trovata here. Fondamentalmente è necessario implementare il filtro effettivo in performFiltering - Suppongo che tu abbia già un modo per interrogare il licenziamento, dal momento che stai attualmente compilando il tuo String[] con versioni non implementate. Vorrete confrontare la query con e senza accenti rispetto alle voci nel vostro array (che vorrete usare con e senza accenti). Alla fine si dovrebbe avere almeno i seguenti quattro test:

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

By deaccenting parole on-the-fly, si avrà solo a fornire il String[] con le parole accentate, mentre la logica di filtraggio (l'adattatore) si prenderà cura della corrispondenza con le parole (de) accentate.

Modifica: come discusso, sotto un'implementazione di esempio in uno dei miei progetti in corso.

Alcune indicazioni:

  1. CustomArrayAdapter è per lo più una classe wrapper che semplifica le attività comuni; per esempio. interazione con un wrapper di riga/supporto di visualizzazione. Fondamentalmente tutto ciò di cui ha bisogno è un costruttore e un'implementazione di updateRow (che ovviamente verrà chiamato dal super metodo 'getView).
  2. CustomRowWrapper dovrebbe essere piuttosto semplice.
  3. ArrayUtil e ArrayUtil.FilterFuction fare attenzione al filtro effettivo. Detto semplicemente, questi sono sostituti di un ciclo for che costruisce un nuovo elenco di tutti gli articoli che corrispondono ad alcuni criteri.

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

    } 

} 
+0

Questo suona davvero molto bene, lo proverò stasera, quando sarò al mio laptop sviluppatore, grazie! Se funziona, lo accetterò come risposta del corso :) – hundeva

+0

Ti ho assegnato la taglia un po 'di tempo fa, e rimarrà così, ma farò una risposta separata in un minuto – hundeva

Problemi correlati