0

I have been at this for almost two weeks now. I believe I have come close, but I can't quite get the final product to work. I have a functionality similar to email in my app. But instead of email addresses, it uses phone numbers. The gmail app on android is able to use a MultiAutoCompleteTextView with chips to display recipient email addresses. That is what I want to do. Through my research and trials, I am able to create the MultiAutoCompleteTextView, but without the chips. There are a number of questions and answers here on the same subject. But invariably, none of the ones I find has an example that binds the data from a user's contact book to the MultiAutoCompleteTextView. All the examples I see use their own made up simple arrays, as if the final step were trivial. But the final step is where I am stuck. Each time I try to bind the contact book to an MultiAutoCompleteTextView with chips, the code fails. So my question is quite extremely specific: How do I bind the contact book to an MultiAutoCompleteTextView with chips? For some context, I have already read Chips widget in Android application and bunch of other articles and responses besides. Is anyone aware of my specific use case? The gmail use case?

EDIT

Following is the code I use with https://github.com/splitwise/TokenAutoComplete . But the getView of my adapter is never called.

code to bind adapter to editText

mAdapter = new ContactAdapter(getActivity(), mPeopleList, R.layout.contacts_row);
multiEdit = (ContactsAutoCompleteView) view.findViewById(R.id.multi_edit);
multiEdit.setAdapter(mAdapter);

code to load contact book

public void PopulatePeopleList() {

    mPeopleList.clear();

    Cursor people = getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null,
            null);

    while (people.moveToNext()) {
        String contactName = people.getString(people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

        String contactId = people.getString(people.getColumnIndex(ContactsContract.Contacts._ID));
        String hasPhone = people.getString(people.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));

        if (Integer.parseInt(hasPhone) > 0) {

            // You know have the number so now query it like this
            Cursor phones = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
            while (phones.moveToNext()) {

                // store numbers and display a dialog letting the user select which.
                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                String numberType = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));

                if (numberType.equals("0")) {
                    numberType = "Work";
                } else if (numberType.equals("1")) {
                    numberType = "Home";
                } else if (numberType.equals("2")) {
                    numberType = "Mobile";
                } else {
                    numberType = "Other";
                }
                mPeopleList.add(new Contact(contactName, phoneNumber, numberType));
            }
            phones.close();
        }
    }
    people.close();

    getActivity().startManagingCursor(people);
}

my adapter

public class ContactAdapter extends ArrayAdapter<Contact> {

    private final Context mContext;
    private final int mRowResourceId;
    private final LayoutInflater mInflater;
    ArrayList<Contact> mContacts;

    public ContactAdapter(Context context, ArrayList<Contact> contacts, int contactsRow) {
        super(context, contactsRow, contacts);
        mContext = context;
        mRowResourceId = contactsRow;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContacts = contacts;
    }

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

        View rowView = convertView;
        if (null == rowView) {
            rowView = mInflater.inflate(mRowResourceId, parent, false);
            ViewHolder viewsHolder = new ViewHolder();
            viewsHolder.name = (TextView) rowView.findViewById(R.id.contact_name);
            viewsHolder.phone = (TextView) rowView.findViewById(R.id.contact_phone);
            viewsHolder.type = (TextView) rowView.findViewById(R.id.contact_type);
            rowView.setTag(viewsHolder);
        }
        ViewHolder viewsHolder = (ViewHolder) rowView.getTag();
        Contact con = mContacts.get(position);// getItem(position);
        viewsHolder.name.setText(con.getName());
        viewsHolder.phone.setText(con.getPhone());
        viewsHolder.type.setText(con.getType());
        return rowView;
    }

    static class ViewHolder {
        TextView name;
        TextView phone;
        TextView type;
    }

}

my contact object: accessors and constructor not shown

public class Contact implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private String phone;
    private String type;
}

My TokenCompleteTextView: ?? what goes inside defaultObject

public class ContactsAutoCompleteView extends TokenCompleteTextView {

public ContactsAutoCompleteView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected View getViewForObject(Object object) {
    Contact p = (Contact) object;

    LayoutInflater l = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    RelativeLayout view = (RelativeLayout) l.inflate(R.layout.contacts_row,
            (ViewGroup) ContactsAutoCompleteView.this.getParent(), false);
    ((TextView) view.findViewById(R.id.contact_name)).setText(p.getName());
    ((TextView) view.findViewById(R.id.contact_phone)).setText(p.getPhone());
    ((TextView) view.findViewById(R.id.contact_type)).setText(p.getType());

    return view;
}

@Override
protected Object defaultObject(String completionText) {
    //what goes here?
}

@Override
public void setSelected(boolean selected) {
    super.setSelected(selected);

}

}

Community
  • 1
  • 1
learner
  • 11,490
  • 26
  • 97
  • 169
  • when I try to use the chips, when I type in the textview nothing happens, no suggestions. Then I run the code in debug mode to find that the adapter is never accessed. – learner Mar 25 '14 at 16:36
  • if your data model is a Cursor why dont you use a SimpleCursorAdapter? – pskink Mar 25 '14 at 16:47
  • @pskink that is what I had before finding a `chip` library. The chip library I am showing requires a Contact object not a `Map – learner Mar 25 '14 at 16:52
  • i already posted a similar solution with searching for names or phone numbers, so whats so hard to add email functionality? http://stackoverflow.com/questions/22443791/multiautocompletetextview-with-contacts-phone-numbers – pskink Mar 25 '14 at 17:04
  • @pskink yes, I remember your help along the way. But the `chips` are very important. Gmail uses the chips. The problem is when I try to include the chips that the code fails. – learner Mar 25 '14 at 17:08
  • chips are no problem to implement, as easy as implementing two one-liner methods – pskink Mar 25 '14 at 19:10
  • and the whole thing is 70 lines of code only :) – pskink Mar 26 '14 at 10:27

1 Answers1

0

Few weeks ago i was in your situation, and what I did was to use a library for the chips

I used this one

as for the bind with the contacts be more specific where are you stuck and what are you get ?

Tomer Mor
  • 7,998
  • 5
  • 29
  • 43
  • Thanks. I will take a look at your link. But as I explain above, when I try to use a chip library, my adapter's `getview` method is never called. – learner Mar 25 '14 at 16:38
  • Actually I just looked at your library. I have tried it. I will edit my answer to show my code that fails with it. But basically I extend ArrayAdapter and pass that to the textview. – learner Mar 25 '14 at 16:39
  • I have edited to show my complete code. Since you have solved this same problem, you may be my hope. Thanks. You may edit your response with the appropriate feedback/hints. thanks. – learner Mar 25 '14 at 16:50
  • also what is your implementation of `defaultObject`? I understand my POJO is more complex than the one in the sample code. – learner Mar 25 '14 at 16:57
  • my Implementation for defaultObject was not supporting and return empty contact – Tomer Mor Mar 25 '14 at 17:42
  • I am showing my entire code, can you spot any mistakes? – learner Mar 25 '14 at 18:00