2013-06-06 15 views
8

Czy istnieje prosty sposób ustawienia listy rozwijanej 2 TextView w widoku AutoCompleteTextView.Jak dodać niestandardową kartę do AutoCompleteTextView?

Istnieje android.R.layout.two_line_list_item Które nie mogłem znaleźć przykłady użycia.

Tak, próbowałem to:

public class TwoLineDropdownAdapter extends BaseAdapter { 

    private LayoutInflater mInflater = null; 
    private Activity activity; 
    public ArrayList<TwoLineDropDown> values = new ArrayList<TwoLineDropDown>(); 

    public TwoLineDropdownAdapter(Activity a, ArrayList<TwoLineDropDown> items) { 

     values = items; 
     activity = a; 
     mInflater = (LayoutInflater) activity 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    public int getCount() { 

     return values.size(); 
    } 

    public TwoLineDropDown getItem(int position) { 

     return values.get(position); 
    } 

    public long getItemId(int position) { 

     return position; 
    } 

    public static class ViewHolder { 

     public TextView title; 
     public TextView description; 
    } 

    public View getView(final int position, View convertView, ViewGroup parent) { 

     ViewHolder holder; 

     if (convertView == null) { 

      holder = new ViewHolder(); 

      convertView = mInflater.inflate(R.layout.dropdown_text_twoline, 
        parent, false); 
      holder.title = (TextView) convertView 
        .findViewById(R.id.text1); 
      holder.description = (TextView) convertView 
        .findViewById(R.id.text2); 

      convertView.setTag(holder); 
     } else { 
      holder = (ViewHolder) convertView.getTag(); 
     } 

     return convertView; 
    } 

    public void add(TwoLineDropDown ei) { 

     values.add(ei); 
    } 
} 

Ale w obliczu problemu tutaj:

TwoLineDropdownAdapter AutoCompleteAdapter = new TwoLineDropdownAdapter(this, items); 
myAutoComplete.setAdapter(AutoCompleteAdapter); 

podczas ustawiania adaptera to mówi:

Związany źle match: Ogólna metoda setAdapter (T) typu AutoCompleteTextView nie ma zastosowania dla argumentów (TwoLineDropdownAdapter). Typ wnioskowany TwoLineDropdownAdapter to nie jest prawidłowym zamiennikiem ograniczonego parametru

Jak rozwiązać ten problem?

Dziękuję

Odpowiedz

7

Zgodnie z dokumentacją, wywnioskowaną rodzaj setAdapter w AutoCompleteTextView jest:

<T extends ListAdapter & Filterable> void setAdapter(T adapter) 

Adapter musi być ListAdapter (co BaseAdapter jest tak daleko, tak dobrze) i sączenia , którego nie ma w BaseAdapter, ani nie jest twoją implementacją adaptera. Chciałbym rozszerzyć ArrayAdapter, który jest filtrowalny, nie mówiąc jest to uproszczenie realizacji (niektóre z metod powielać metod ArrayAdapter do tego samego rezultatu):

public class TwoLineDropdownAdapter extends ArrayAdapter<TwoLineDropDown> { 

    private LayoutInflater mInflater = null; 
    private Activity activity; 

    public TwoLineDropdownAdapter(Activity a, ArrayList<TwoLineDropDown> items) { 
     super(a, 0, items); 
     activity = a; 
     mInflater = (LayoutInflater) activity 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    public static class ViewHolder { 

     public TextView title; 
     public TextView description; 
    } 

    public View getView(final int position, View convertView, ViewGroup parent) { 

     ViewHolder holder; 

     if (convertView == null) { 

      holder = new ViewHolder(); 

      convertView = mInflater.inflate(R.layout.dropdown_text_twoline, 
        parent, false); 
      holder.title = (TextView) convertView 
        .findViewById(R.id.text1); 
      holder.description = (TextView) convertView 
        .findViewById(R.id.text2); 

      convertView.setTag(holder); 
     } else { 
      holder = (ViewHolder) convertView.getTag(); 
     } 

     return convertView; 
    } 
} 
+8

Zastosowałem tę metodę, ale nie pojawia się autouzupełnianie. – tony9099

+0

można zastąpić "rozszerza ListAdapter & Filterable" do BaseAdapter ?, mówię: adapter do adaptera? – delive

+0

@dodaj, możesz zastąpić 'ListAdapter' dowolnie wybraną podklasą. – njzk2

15

Oto kod działa dla mnie,

Ustaw ten adapter autocompletetextview

AutoCompleteTextView etProductSearch = (AutoCompleteTextView)getView().findViewById(R.id.edtSearchBoxTakeOrder); 
ProductSearchAdapter adapter = new ProductSearchAdapter(getActivity(), android.R.layout.simple_dropdown_item_1line, productList); 
etProductSearch.setAdapter(adapter); 

klasa ProductSearchAdapter

import android.content.Context; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.Filter; 
import android.widget.TextView; 

public class ProductSearchAdapter extends ArrayAdapter<ProductDataModel> { 
    private ArrayList<ProductDataModel> items; 
    private ArrayList<ProductDataModel> itemsAll; 
    private ArrayList<ProductDataModel> suggestions; 
    private int viewResourceId; 

    @SuppressWarnings("unchecked") 
    public ProductSearchAdapter(Context context, int viewResourceId, 
      ArrayList<ProductDataModel> items) { 
     super(context, viewResourceId, items); 
     this.items = items; 
     this.itemsAll = (ArrayList<ProductDataModel>) items.clone(); 
     this.suggestions = new ArrayList<ProductDataModel>(); 
     this.viewResourceId = viewResourceId; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
        Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(viewResourceId, null); 
     } 
     ProductDataModel product = items.get(position); 
     if (product != null) { 
       TextView productLabel = (TextView) v.findViewById(android.R.id.text1); 
      if (productLabel != null) { 
       productLabel.setText(product.getProductName()); 
      } 
     } 
     return v; 
    } 

    @Override 
    public Filter getFilter() { 
     return nameFilter; 
    } 

    Filter nameFilter = new Filter() { 
     public String convertResultToString(Object resultValue) { 
      String str = ((ProductDataModel) (resultValue)).getProductName(); 
      return str; 
     } 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      if (constraint != null) { 
       suggestions.clear(); 
       for (ProductDataModel product : itemsAll) { 
        if (product.getProductName().toLowerCase() 
          .startsWith(constraint.toString().toLowerCase())) { 
         suggestions.add(product); 
        } 
       } 
       FilterResults filterResults = new FilterResults(); 
       filterResults.values = suggestions; 
       filterResults.count = suggestions.size(); 
       return filterResults; 
      } else { 
       return new FilterResults(); 
      } 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, 
       FilterResults results) { 
      @SuppressWarnings("unchecked") 
      ArrayList<ProductDataModel> filteredList = (ArrayList<ProductDataModel>) results.values; 
      if (results != null && results.count > 0) { 
       clear(); 
       for (ProductDataModel c : filteredList) { 
        add(c); 
       } 
       notifyDataSetChanged(); 
      } 
     } 
    }; 

} 
+0

Dziękujemy! To było naprawdę pomocne! Miałem problem - lista rozwijana w moim AutoCompleteTextView nie pojawiła się, a metoda getView mojej niestandardowej karty nie została wywołana. Jedyne, co musiałem zrobić, to dodanie metody getFilter, jak na tym przykładzie –

0

Uważam, że najłatwiejszym podejściem jest przedłużenie SimpleAdapter.

public class MyAdapter extends android.widget.SimpleAdapter { 

    static ArrayList<Map<String, String>> toMapList(Collection<MyObject> objectsCollection) { 
     ArrayList<Map<String, String>> objectsList = new ArrayList<Map<String, String>>(objectsCollection.size()); 
     for (MyObject obj : objectsCollection) { 
      Map<String, String> map = new HashMap<String, String>(); 
      map.put("name", obj.getName()); 
      map.put("details", obj.getDetails()); 
      objectsList.add(map); 
     }; 
     return objectsList; 
    } 

    public MyAdapter(Context context, Collection<MyObject> objects) { 

     super(context, toMapList(objects), 
       R.layout.auto_complete_layout, new String[] {"name", "description"}, new int[] {R.id.name, R.id.description}); 
    } 
} 

Główną wadą jest to, że to przyniesie kandydatów na podstawie dowolnej przestrzeni oddzielonych słowem w każdej nazwy lub opisu. Jeśli dodasz inne pole do swojego auto_complete_layout, będzie ono również zaangażowane w dopasowywanie.

W związku z tym zakończyłem przepisywanie prostego adaptera w celu lepszego dopasowania do moich potrzeb, usuwając znaczną część kosztów ogólnych, które nie były istotne dla mojego przypadku użycia. Ale kilka linii powyżej daje dobry początek i zapewnia solidne odniesienie do rozpoczęcia dostosowywania.

Powiązane problemy