2012-10-02 21 views
8

Używam niestandardowego adaptera z funkcją AutoCompleteTextView. Działa dobrze na emulatorze i moim tablecie. Jednak w moim telefonie występuje problem w trybie poziomym. Wskazówki autouzupełniania pokazane w tym trybie to informacje o obiekcie, a nie tekst. Jednak po wybraniu dowolnego elementu pola zostaną poprawnie wypełnione tekstem w odpowiednich polach.Android AutoCompleteTextView wyświetla informacje o obiekcie zamiast tekstu w trybie poziomym.

Automatyczne uzupełnianie dla innych pól opartych na systemie Android Adapter Array Adapter działa dobrze.

Czy muszę coś z tym zrobić w moim adapterze niestandardowym? Widziałem tylko jedno podobne pytanie na SO. Jedną z odpowiedzi na to pytanie było mówienie o przesłonięciu metody toString, ale nie mogłem tego zrozumieć, aby zaimplementować ją w moim kodzie.

Wszelkie wskazówki będą mile widziane? Daj mi znać, jeśli potrzebujesz więcej informacji.

EDIT: Dodano mój kod źródłowy zwyczaj adaptera ....

public class Part_Mstr_Info 
    { 
    private long part_id; 
    private String name, desg, org, dept; 

    public Part_Mstr_Info(long part_id, String name, String desg, String org, String dept) 
    { 
     this.part_id = part_id; 
     this.name = name; 
     this.desg = desg; 
     this.org = org; 
     this.dept = dept; 
    } 
    public long get_part_id() { return part_id; } 
    public String get_name() { return name; } 
    public String get_desg() { return desg; } 
    public String get_org() { return org; } 
    public String get_dept() { return dept; } 
} 

public class CustomAdapter extends ArrayAdapter<Part_Mstr_Info> implements Filterable{ 
    private List<Part_Mstr_Info> entries; 
    private ArrayList<Part_Mstr_Info> orig; 
    private Activity activity; 
    private ArrayFilter myFilter; 

    public CustomAdapter(Activity a, int textViewResourceId, ArrayList<Part_Mstr_Info> entries) { 
    super(a, textViewResourceId, entries); 
    this.entries = entries; 
    this.activity = a; 
} 

public static class ViewHolder{ 
    public TextView tv_ac_name; 
    public TextView tv_ac_desg; 
    public TextView tv_ac_org; 
    public TextView tv_ac_dept; 
} 

@Override 
public int getCount(){ 
     return entries!=null ? entries.size() : 0; 
} 

@Override 
public Part_Mstr_Info getItem(int index) { 
    return entries.get(index); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View v = convertView; 
    ViewHolder holder; 
    if (v == null) { 
     LayoutInflater vi = 
      (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     v = vi.inflate(R.layout.ac_name_list, null); 
     holder = new ViewHolder(); 
     holder.tv_ac_name = (TextView) v.findViewById(R.id.ac_name); 
     holder.tv_ac_desg = (TextView) v.findViewById(R.id.ac_desg); 
     holder.tv_ac_org = (TextView) v.findViewById(R.id.ac_org); 
     holder.tv_ac_dept = (TextView) v.findViewById(R.id.ac_dept); 
     v.setTag(holder); 
    } 
    else 
     holder=(ViewHolder)v.getTag(); 

    final Part_Mstr_Info custom = entries.get(position); 
    if (custom != null) { 
     holder.tv_ac_name.setText(custom.get_name()); 
     holder.tv_ac_desg.setText(custom.get_desg()); 
     holder.tv_ac_org.setText(custom.get_org()); 
     holder.tv_ac_dept.setText(custom.get_dept()); 
    } 
    return v; 
} 

@Override 
public Filter getFilter() { 
    if (myFilter == null){ 
     myFilter = new ArrayFilter(); 
    } 
    return myFilter; 
} 

@Override 
public String toString() { 
    String temp = getClass().getName(); 
    return temp; 
} 

private class ArrayFilter extends Filter { 
    @Override 
    protected FilterResults performFiltering(CharSequence constraint) { 
     FilterResults results = new FilterResults(); 
     if (orig == null) 
      orig = new ArrayList<Part_Mstr_Info>(entries); 
     if (constraint != null && constraint.length() != 0) { 
      ArrayList<Part_Mstr_Info> resultsSuggestions = new ArrayList<Part_Mstr_Info>(); 
      for (int i = 0; i < orig.size(); i++) { 
       if(orig.get(i).get_name().toLowerCase().startsWith(constraint.toString().toLowerCase())){ 
        resultsSuggestions.add(orig.get(i)); 
       } 
      } 

      results.values = resultsSuggestions; 
      results.count = resultsSuggestions.size(); 

     } 
     else { 
      ArrayList <Part_Mstr_Info> list = new ArrayList <Part_Mstr_Info>(orig); 
      results.values = list; 
      results.count = list.size(); 
     } 
     return results; 
    } 

    @Override 
    @SuppressWarnings("unchecked") 
    protected void publishResults(CharSequence constraint, FilterResults results) { 
     clear(); 
     ArrayList<Part_Mstr_Info> newValues = (ArrayList<Part_Mstr_Info>) results.values; 
     if(newValues !=null) { 
      for (int i = 0; i < newValues.size(); i++) { 
       add(newValues.get(i)); 
      } 
      if(results.count>0) { 
       notifyDataSetChanged(); 
      } else { 
       notifyDataSetInvalidated(); 
      } 
     }  

    } 

} 

Odpowiedz

6

Tak, po prostu zastąpić metodę toString() na swojej POJO.

public class MyObject { 
    ... 

    @Override 
    public String toString() { 
     return showThisStringOnAdapter; 
    } 
} 
+0

Próbowałem tego, ale to nie działa. Prawdopodobnie dlatego, że nadpisuję metody filtrowania i getview ... Kiedy próbowałem debugować, ścieżka wykonania nie przechodzi w ogóle do metody toString. Dodam więcej szczegółów i kod do mojego pierwotnego pytania, aby wyjaśnić ... – Sriman

+0

Na podstawie tego, co widzę w sare źródła ArrayAdapter, czuję, że muszę coś zrobić w metodzie getView, ale nie jestem pewien, co dokładnie trzeba zrobić ... Jak już powiedziałem, działa to doskonale na tabletach i emulatorach. Problem występuje tylko w telefonie w trybie poziomym, gdy prawdopodobnie nie ma wystarczająco dużo miejsca, aby wyświetlić niestandardowy widok, który mam ... – Sriman

+0

Po zobaczeniu Twojego niestandardowego adaptera, który nie powinien mieć żadnych problemów, wydaje się, że przyczyną jest 'ConfigChanges', czy obrócić telefon z portretu na krajobraz? Jeśli tak, spójrz na [tutaj] (http://stackoverflow.com/questions/456211/activity-restart-on-rotation-android), może ci pomóc – Aprian

3

Utwórz niestandardową klasę, która rozszerza się o <AutoCompleteTextView />. Na przykład:

package lt.irisas.akcija.utils; 

import lt.irisas.akcija.data.ItemsModel; 
import android.content.Context; 
import android.database.Cursor; 
import android.util.AttributeSet; 
import android.widget.AutoCompleteTextView; 

/** Customizing AutoCompleteTextView to return Cursor column info as String 
*/ 
public class CustomAutoCompleteTextView extends AutoCompleteTextView { 

    public CustomAutoCompleteTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    /* Overriding this method and returning String type solves the problem */ 
    @Override 
    protected CharSequence convertSelectionToString(Object selectedItem) { 
     Cursor c = (Cursor) selectedItem; 

     return c.getString(c.getColumnIndex("COLUMN_NAME")); 
    } 
} 

Ale zamiast <AutoCompleteTextView/> należy użyć niestandardowego jeden. Na przykład:

<LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal" > 

     <lt.irisas.akcija.utils.CustomAutoCompleteTextView 
      android:id="@+id/search_field" 
      android:layout_width="0dip" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:singleLine="true" 
      android:imeOptions="actionSearch" > 
     </lt.irisas.akcija.utils.CustomAutoCompleteTextView> 
</LinearLayout> 

Mam nadzieję, że to pomaga. Przynajmniej dla mnie.

+0

Nie działa dla mnie ... Powodem jest to, że muszę zwrócić obiekt klasy Part_Mstr_Info aby uzyskać od niego nazwę, desg, org i dept. Moje autouzupełnione sugestie są dwiema liniami, każda z imionami na pierwszym i pozostałych trzech polach na drugim ... Więc nie mogę po prostu zwrócić ciągu .. Muszę zwrócić kompletny obiekt ... – Sriman

0

Znalazłem odpowiedź ostatni raz. Miałem ten sam problem i wydaje się, że autouzupełnianie używa metody convertToString() w trybie poziomym zamiast metody newView() i bindView(). Musisz zwrócić wszystkie dane kursora do jednego ciągu bez "\ n", tak jak elementy będą wyświetlane poziomo nad klawiaturą programową.

przykład w AutoCompleteTextViewAdapter, dodać metodę:

 @Override 
    public CharSequence convertToString(Cursor cursor) { 


     String name = cursor.getString(0); 
     String number = cursor.getString(1); 


     return name+" : "+number; 
    } 

Testowałem go z telefonem Xperia U i innymi Galaxy Note i to działa. To takie proste. Oczywiście zapełnisz tę metodę w zależności od tego, co chcesz wyświetlić.

+0

Dzięki ... będę spróbuj tego za kilka dni i zgłoś, co się dzieje ... – Sriman

0

to jest odpowiedź:

adapter.setCursorToStringConverter(new CursorToStringConverter() { 
    @Override 
    public CharSequence convertToString(Cursor c) { 
     return c.getString(c.getColumnIndexOrThrow("Column")); 
    } 
}); 
10

Prawo sposobem na to jest przesłanianie metody Filter#convertResultToString(Object) w ArrayFilter prywatnej klasie.

Jak wspomniano w dokumentach Android

publicznego CharSequence convertResultToString (resultValue Object)

konwersję wartości odfiltrowanej, osadzona w CharSequence. Podklasy powinny zastąpić tę metodę, aby przekonwertować wyniki. Domyślna implementacja zwraca pusty łańcuch dla wartości pustych lub domyślnej Ciąg reprezentacji wartości.

W Twoim przypadku powinno to być coś takiego:

private class ArrayFilter extends Filter { 
    @Override 
    public CharSequence convertResultToString(Object resultValue) { 
     return ((Part_Mstr_Info) resultValue).get_name(); 
    } 

Dodanie tej metody pozwoli AutoCompleteTextView dostarczenie koryguje podpowiedzi (w widoku poziomym) zamiast odniesień do obiektu lub domyślna toString