Android AutoCompleteTextView shows object information instead of text in landscape mode
Asked Answered
R

5

12

I am using a Custom Adapter with AutoCompleteTextView. It works fine on the emulator and my tablet. However, there is an issue on my phone in landscape mode. The auto complete hints being shown in this mode are object info rather than text. However, when I select any item the fields gets populated correctly with text in the respective fields.

Auto Complete for other fields that are based on Android Stock Array Adapter works fine.

Do I have to do something for this in my Custom Adapter? I saw only one similar question on SO. One response for that question was talking about overriding the toString method but I couldn't understand it enough to implement in my code.

Any guidance will be greatly appreciated? Please let me know if you need more information.

EDIT: Added my custom adapter source code....

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

    }

}
Rene answered 2/10, 2012 at 0:23 Comment(0)
M
11

The right way to do it is overriding the method Filter#convertResultToString(Object) in your ArrayFilter private class.

As said in the Android documentation

public CharSequence convertResultToString (Object resultValue)

Converts a value from the filtered set into a CharSequence. Subclasses should override this method to convert their results. The default implementation returns an empty String for null values or the default String representation of the value.

In your case it should be something like that:

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

Adding this method will allow the AutoCompleteTextView to provide corrects hints (in landscape view) instead of object references or default toString

Micelle answered 6/5, 2015 at 11:38 Comment(0)
G
10

Yes, just override the toString() method on your POJO.

public class MyObject {
    ...

    @Override
    public String toString() {
        return showThisStringOnAdapter;
    }
}
Gunter answered 2/10, 2012 at 1:14 Comment(6)
I tried this but it doesn't work.. Probably because I am overriding filter and getview methods also... When I tried to debug, the execution path doesn't go into the toString method at all.. I will add more details and code to my original question to clarify...Rene
Based on what I see in the ArrayAdapter source doe, I feel I have to do something in the getView method but not sure what exactly needs to be done... As I said it works perfectly on tablets and emulator. The issue is only on phone in landscape mode when there is not probably enough space to show the custom view that I have...Rene
After seeing your CustomAdapter which should not have any probs, seems like the cause is ConfigChanges, did you rotate the phone from portrait to landscape? If yes, look at here, may help youGunter
My app is designed to work only in landscape mode and I force it using a parameter in the manifest. Here is what I have... android:screenOrientation="sensorLandscape" android:configChanges="keyboardHidden"....... So there is no chance of rotating it from portrait to landscape... Also, I am wondering why it works on my tablet and emulator but not on phone....Rene
Nice thinking, quick and easy solution :)Niggerhead
Very helpful, you saved my dayMathews
D
3

Create custom class which extends <AutoCompleteTextView />. For example:

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

But instead of <AutoCompleteTextView/> you must use your custom one. For example:

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

Hope it helps. Well at least it did for me.

Desultory answered 17/10, 2012 at 12:54 Comment(1)
Doesn't work for me... The reason is that I need to return an object of the class Part_Mstr_Info so that I can get the name, desg, org and dept from it. My auto complete suggestions are two lines each with name on the first and the other three fields on the second... So I cannot just return a string.. I need to return the complete object...Rene
I
0

I've found the answer last time. I had the same issue and it seems that autocomplete uses convertToString() method in landscape mode instead of newView() and bindView() method. You have to return all your cursor data into one single String without "\n" like the items will be displayed horizontaly over the softkeyboard.

Example in your AutoCompleteTextViewAdapter, add the method :

        @Override
    public CharSequence convertToString(Cursor cursor) {


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


        return name+" : "+number;
    }

I tested it with my phone Xperia U and another Galaxy Note and it works. It is that simple. Of course, you will populate this method depending what you want it to display.

Iron answered 25/1, 2013 at 10:10 Comment(0)
K
0

this is your answer :

adapter.setCursorToStringConverter(new CursorToStringConverter() {
    @Override
    public CharSequence convertToString(Cursor c) {
        return c.getString(c.getColumnIndexOrThrow("Column"));
    }
});
Kidwell answered 14/1, 2014 at 19:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.