2012-03-11 3 views
5

У меня есть 3 AutoCompleteTextViews, и я хотел бы зарегистрировать на них 2 адаптера String []. В настоящее время я делаю это:Адаптер AutoCompleteTextView, «скрытый» адаптер?

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

Допустим, мой пользователь хочет ввести «Középmező», он начинает набирать «Козе», и он будет предложено выбрать Középmező, пока это, не очень просто. Но что, если пользователь слишком ленив, чтобы набирать акценты (и многие из них ленивы), таким образом он будет вводить только Kozepmezo, тогда он не получит никакого предложения, так как в моей String нет Козепмезо. То, что я хочу, если он набирает «Козе», ему следует предложить Középmező, так что, даже если он не использует акценты, ему всегда будет предлагаться фактическое слово с акцентами.

В настоящее время у меня довольно глупое решение, у меня есть String [] с удвоенным размером оригинала [], первая половина содержит слова с акцентами, вторая содержит разгромленные версии. Итак, теперь, если он наберет Кёзе, ему предложит Középmező, и если он наберет Koze, ему будет предложено Kozepmezo. Он работает, потому что сервер может обрабатывать обе версии, но он просто выглядит глупым, и я хочу его решить.

Из чего я понимаю, я должен сделать полный пользовательский адаптер. Это лучший подход, или есть ли какое-либо решение, включенное в SDK? Если я должен сделать пользовательский адаптер, может ли кто-нибудь указать мне в правильном направлении, как это сделать? :)

EDIT: добавлен мой собственный ответ, должен работать для всех, приветствия для другого ответа, который направил меня на хорошее направление!

ответ

1

Окей, после того, как много боли в заднице дело с этим, вот что я сделал в конце. Это НЕ хорошая практика, и я могу сделать это неправильно, но, по крайней мере, она отлично работает сейчас.

Просто ctrl + c, ctrl + v исходный код BaseAdapter и ctrl + c, ctrl + v исходный код ArrayAdapter. Теперь рассмотрим частный внутренний класс ArrayFilter, особенно метод performFiltering. Измените (не переопределяйте!) Его, сколько хотите, в моем случае я добавил много вещей .replace («x», «y») для деактивирующей части.

Независимо от того, что я пробовал, либо создавалась непредсказуемая сила закрытия (много, и полностью случайных), либо я просто не мог этого сделать, поскольку слишком много методов/переменных являются частными, а не защищенными. Должен сказать, что Google должен пересмотреть эти коды ...

Примечание: вам не нужно ctrl + c ctrl + v коды BaseAdapter, так как это открытый абстрактный класс, но эй, это не так. большая часть кода, и таким образом все там, хорошо видимое для вас.

cheers

+0

Слишком плохо, что вы слышали, «Я могу решить вашу проблему с помощью моего предыдущего решения. Если вы (все еще) заинтересованы, я могу опубликовать решение, которое я написал пару недель назад? Мы используем внутреннюю библиотеку для упрощения общих задач, но фильтрующая часть должна быть относительно нетронутой. –

+0

Я всегда интересовался лучшими решениями! :) Если вы не против, я бы посмотрел на него. Во всяком случае, ваш ответ указал мне в направлении, которое заставило меня решить мою проблему, поэтому большой вам уже нужен. Плюс я думал о том, чтобы полностью переписать некоторые части этого массива ArrayAdapter, так как для общего он может быть стабильным, но для моего случая ему не нужны дополнительные массивы, что уменьшает время памяти/процессора, которое потребуется для фильтрации. – hundeva

+0

Хорошо, я добавил код, который я сейчас использую в одном из моих проектов, к моему более раннему ответу. Самый интересный бит для вас - переопределенный метод getFilter. Надеюсь, это будет иметь смысл для вас. :) –

1

я бы действительно пойти для пользовательского адаптера, в котором вы предоставляете свои собственные фильтр, чтобы соответствовать как акцентированным, так и деактивированным обозначениям.

Пример осуществления, выполняющего только это, можно найти here. В основном вам нужно будет реализовать фактическую фильтрацию в performFiltering. Я предполагаю, что у вас уже есть путь к деациентным запросам, так как вы в настоящее время заполняете свои String[] с разрозненными версиями. Вы захотите сравнить запрос с акцентами и без них с элементами вашего массива (которые вы хотите использовать с акцентами и без них). В конце концов, вы должны иметь по крайней мере следующие четыре испытания:

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

По deaccenting слова на лету, вы только должны обеспечить String[] с диакритическими словами, в то время как фильтрование логика (в адаптере) позаботится о совпадении с (de) акцентированными словами.

Редактировать: как обсуждалось ниже примера реализации в одном из моих текущих проектов.

Некоторые указатели:

  1. CustomArrayAdapter в основном класс-оболочка, которая упрощает общие задачи; например взаимодействие с держателем строки/держателем вида. В основном все, что ему нужно, это конструктор и реализация updateRow (который, очевидно, будет вызван из метода суперкласса getView).
  2. CustomRowWrapper должно быть довольно простым.
  3. ArrayUtil и ArrayUtil.FilterFuction заботиться о фактической фильтрации. Просто сказано, что они действуют как замена цикла for, который создает новый список всех элементов, соответствующих некоторым критериям.

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

Это звучит очень хорошо, я попробую сегодня вечером, когда я буду на своем ноутбуке-разработчике, THX! Если это сработает, я соглашусь с ним в качестве ответа на вызов :) – hundeva

+0

Я наградил вас щедростью некоторое время назад, и так будет, но я собираюсь сделать отдельный ответ за минуту – hundeva

Смежные вопросы