1b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linpackage com.android.ex.chips;
2b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
3b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.content.Context;
46c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Caoimport android.content.res.Resources;
5b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.graphics.Bitmap;
6b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.graphics.BitmapFactory;
74db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Caoimport android.graphics.drawable.StateListDrawable;
8b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.net.Uri;
94db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Caoimport android.support.annotation.DrawableRes;
104db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Caoimport android.support.annotation.IdRes;
114ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Caoimport android.support.annotation.LayoutRes;
12e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedyimport android.support.annotation.Nullable;
136f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedyimport android.support.v4.view.MarginLayoutParamsCompat;
14e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedyimport android.text.SpannableStringBuilder;
15e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedyimport android.text.Spanned;
16b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.text.TextUtils;
17e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedyimport android.text.style.ForegroundColorSpan;
18b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.text.util.Rfc822Tokenizer;
19b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.view.LayoutInflater;
20b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.view.View;
21b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.view.ViewGroup;
226f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedyimport android.view.ViewGroup.MarginLayoutParams;
23b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.widget.ImageView;
24b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport android.widget.TextView;
25b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
26b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport com.android.ex.chips.Queries.Query;
27b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
28b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin/**
29b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin * A class that inflates and binds the views in the dropdown list from
30b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin * RecipientEditTextView.
31b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin */
32b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linpublic class DropdownChipLayouter {
33b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
34b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * The type of adapter that is requesting a chip layout.
35b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
36b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    public enum AdapterType {
37b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        BASE_RECIPIENT,
38b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        RECIPIENT_ALTERNATES,
39b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        SINGLE_RECIPIENT
40b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
41b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
424db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    public interface ChipDeleteListener {
434db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        void onChipDelete();
444db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    }
454db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
46b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    private final LayoutInflater mInflater;
47b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    private final Context mContext;
484db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    private ChipDeleteListener mDeleteListener;
49b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    private Query mQuery;
506f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy    private int mAutocompleteDividerMarginStart;
51b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
52b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    public DropdownChipLayouter(LayoutInflater inflater, Context context) {
53b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        mInflater = inflater;
54b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        mContext = context;
556f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy        mAutocompleteDividerMarginStart =
566f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                context.getResources().getDimensionPixelOffset(R.dimen.chip_wrapper_start_padding);
57b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
58b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
59b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    public void setQuery(Query query) {
60b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        mQuery = query;
61b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
62b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
634db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    public void setDeleteListener(ChipDeleteListener listener) {
644db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        mDeleteListener = listener;
654db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    }
664db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
676f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy    public void setAutocompleteDividerMarginStart(int autocompleteDividerMarginStart) {
686f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy        mAutocompleteDividerMarginStart = autocompleteDividerMarginStart;
696f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy    }
70b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
71b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
72b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Layouts and binds recipient information to the view. If convertView is null, inflates a new
73b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * view with getItemLaytout().
74b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     *
75b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param convertView The view to bind information to.
76b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param parent The parent to bind the view to if we inflate a new view.
77b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param entry The recipient entry to get information from.
78b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param position The position in the list.
79b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param type The adapter type that is requesting the bind.
80b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @param constraint The constraint typed in the auto complete view.
81b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     *
82b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * @return A view ready to be shown in the drop down list.
83b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
84b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    public View bindView(View convertView, ViewGroup parent, RecipientEntry entry, int position,
85b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        AdapterType type, String constraint) {
864db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        return bindView(convertView, parent, entry, position, type, constraint, null);
874db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    }
884db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
894db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    /**
904db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao     * See {@link #bindView(View, ViewGroup, RecipientEntry, int, AdapterType, String)}
916c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao     * @param deleteDrawable a {@link android.graphics.drawable.StateListDrawable} representing
926c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao     *     the delete icon. android.R.attr.state_activated should map to the delete icon, and the
936c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao     *     default state can map to a drawable of your choice (or null for no drawable).
944db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao     */
954db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    public View bindView(View convertView, ViewGroup parent, RecipientEntry entry, int position,
964db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao            AdapterType type, String constraint, StateListDrawable deleteDrawable) {
97b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        // Default to show all the information
98e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        CharSequence[] styledResults =
99e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                getStyledResults(constraint, entry.getDisplayName(), entry.getDestination());
100e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        CharSequence displayName = styledResults[0];
101e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        CharSequence destination = styledResults[1];
102b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        boolean showImage = true;
103b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        CharSequence destinationType = getDestinationType(entry);
104b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
105b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        final View itemView = reuseOrInflateView(convertView, parent, type);
106b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
107b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        final ViewHolder viewHolder = new ViewHolder(itemView);
108b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
109b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        // Hide some information depending on the entry type and adapter type
110b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        switch (type) {
111b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case BASE_RECIPIENT:
112b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                if (TextUtils.isEmpty(displayName) || TextUtils.equals(displayName, destination)) {
113b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    displayName = destination;
114b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
115b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    // We only show the destination for secondary entries, so clear it only for the
116b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    // first level.
117b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    if (entry.isFirstLevel()) {
118b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        destination = null;
119b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    }
120b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                }
121b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
122b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                if (!entry.isFirstLevel()) {
123b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    displayName = null;
124b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    showImage = false;
125b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                }
126b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao
127b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao                // For BASE_RECIPIENT set all top dividers except for the first one to be GONE.
128b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao                if (viewHolder.topDivider != null) {
129b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao                    viewHolder.topDivider.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
1306f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                    MarginLayoutParamsCompat.setMarginStart(
1316f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                            (MarginLayoutParams) viewHolder.topDivider.getLayoutParams(),
1326f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                            mAutocompleteDividerMarginStart);
1336f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                }
1346f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                if (viewHolder.bottomDivider != null) {
1356f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                    MarginLayoutParamsCompat.setMarginStart(
1366f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                            (MarginLayoutParams) viewHolder.bottomDivider.getLayoutParams(),
1376f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy                            mAutocompleteDividerMarginStart);
138b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao                }
139b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                break;
140b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case RECIPIENT_ALTERNATES:
141b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                if (position != 0) {
142b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    displayName = null;
143b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    showImage = false;
144b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                }
145b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                break;
146b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case SINGLE_RECIPIENT:
147b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                destination = Rfc822Tokenizer.tokenize(entry.getDestination())[0].getAddress();
148b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                destinationType = null;
149b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
150b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
151b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        // Bind the information to the view
152b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        bindTextToView(displayName, viewHolder.displayNameView);
153b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        bindTextToView(destination, viewHolder.destinationView);
154b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        bindTextToView(destinationType, viewHolder.destinationTypeView);
155b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        bindIconToView(showImage, entry, viewHolder.imageView, type);
1566c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao        bindDrawableToDeleteView(deleteDrawable, entry.getDisplayName(), viewHolder.deleteView);
157b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
158b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return itemView;
159b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
160b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
161b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
1624ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao     * Returns a new view with {@link #getItemLayoutResId(AdapterType)}.
163b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
1644ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao    public View newView(AdapterType type) {
1654ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        return mInflater.inflate(getItemLayoutResId(type), null);
166b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
167b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
168b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
169b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns the same view, or inflates a new one if the given view was null.
170b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
171b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    protected View reuseOrInflateView(View convertView, ViewGroup parent, AdapterType type) {
1724ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        int itemLayout = getItemLayoutResId(type);
173b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        switch (type) {
174b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case BASE_RECIPIENT:
175b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case RECIPIENT_ALTERNATES:
176b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                break;
177b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            case SINGLE_RECIPIENT:
1784ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                itemLayout = getAlternateItemLayoutResId(type);
179b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                break;
180b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
181b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return convertView != null ? convertView : mInflater.inflate(itemLayout, parent, false);
182b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
183b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
184b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
185b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Binds the text to the given text view. If the text was null, hides the text view.
186b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
187b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    protected void bindTextToView(CharSequence text, TextView view) {
188b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        if (view == null) {
189b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            return;
190b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
191b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
192b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        if (text != null) {
193b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            view.setText(text);
194b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            view.setVisibility(View.VISIBLE);
195b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        } else {
196b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            view.setVisibility(View.GONE);
197b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
198b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
199b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
200b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
201b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Binds the avatar icon to the image view. If we don't want to show the image, hides the
202b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * image view.
203b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
204b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    protected void bindIconToView(boolean showImage, RecipientEntry entry, ImageView view,
205b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        AdapterType type) {
206b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        if (view == null) {
207b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            return;
208b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
209b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
210b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        if (showImage) {
211b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            switch (type) {
212b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                case BASE_RECIPIENT:
213b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    byte[] photoBytes = entry.getPhotoBytes();
214b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    if (photoBytes != null && photoBytes.length > 0) {
215b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        final Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
216b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                            photoBytes.length);
217b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        view.setImageBitmap(photo);
218b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    } else {
219b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        view.setImageResource(getDefaultPhotoResId());
220b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    }
221b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    break;
222b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                case RECIPIENT_ALTERNATES:
223b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    Uri thumbnailUri = entry.getPhotoThumbnailUri();
224b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    if (thumbnailUri != null) {
225b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        // TODO: see if this needs to be done outside the main thread
226b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        // as it may be too slow to get immediately.
2277a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        view.setImageURI(thumbnailUri);
228b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    } else {
229b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                        view.setImageResource(getDefaultPhotoResId());
230b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    }
231b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    break;
232b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                case SINGLE_RECIPIENT:
233b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                default:
234b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin                    break;
235b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            }
236b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            view.setVisibility(View.VISIBLE);
237b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        } else {
238b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            view.setVisibility(View.GONE);
239b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
240b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
241b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
2426c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao    protected void bindDrawableToDeleteView(final StateListDrawable drawable, String recipient,
2436c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao            ImageView view) {
2444db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        if (view == null) {
2454db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao            return;
2464db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        }
2474db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        if (drawable == null) {
2484db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao            view.setVisibility(View.GONE);
249ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao        } else {
2506c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao            final Resources res = mContext.getResources();
251ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao            view.setImageDrawable(drawable);
2526c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao            view.setContentDescription(
2536c3f99e2e9f0f1ada622c7ab25876b69fa82b146Jin Cao                    res.getString(R.string.dropdown_delete_button_desc, recipient));
254ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao            if (mDeleteListener != null) {
255ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                view.setOnClickListener(new View.OnClickListener() {
256ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                    @Override
257ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                    public void onClick(View view) {
258ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                        if (drawable.getCurrent() != null) {
259ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                            mDeleteListener.onChipDelete();
260ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                        }
2614db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao                    }
262ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao                });
263ffc0111fa742c72f2457cecc1116e4ea3c6c8c6eJin Cao            }
2644db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        }
2654db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    }
2664db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
267b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    protected CharSequence getDestinationType(RecipientEntry entry) {
268b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return mQuery.getTypeLabel(mContext.getResources(), entry.getDestinationType(),
269b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            entry.getDestinationLabel()).toString().toUpperCase();
270b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
271b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
272b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
273b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns a layout id for each item inside auto-complete list.
274b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     *
275b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Each View must contain two TextViews (for display name and destination) and one ImageView
276b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * (for photo). Ids for those should be available via {@link #getDisplayNameResId()},
277b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * {@link #getDestinationResId()}, and {@link #getPhotoResId()}.
278b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
2794ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao    protected @LayoutRes int getItemLayoutResId(AdapterType type) {
2804ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        switch (type) {
2814ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            case BASE_RECIPIENT:
2824ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_autocomplete_recipient_dropdown_item;
2834ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            case RECIPIENT_ALTERNATES:
2844ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_recipient_dropdown_item;
2854ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            default:
2864ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_recipient_dropdown_item;
2874ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        }
288b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
289b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
290b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
291b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns a layout id for each item inside alternate auto-complete list.
292b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     *
293b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Each View must contain two TextViews (for display name and destination) and one ImageView
294b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * (for photo). Ids for those should be available via {@link #getDisplayNameResId()},
295b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * {@link #getDestinationResId()}, and {@link #getPhotoResId()}.
296b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
2974ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao    protected @LayoutRes int getAlternateItemLayoutResId(AdapterType type) {
2984ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        switch (type) {
2994ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            case BASE_RECIPIENT:
3004ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_autocomplete_recipient_dropdown_item;
3014ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            case RECIPIENT_ALTERNATES:
3024ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_recipient_dropdown_item;
3034ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            default:
3044ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao                return R.layout.chips_recipient_dropdown_item;
3054ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        }
306b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
307b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
308b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
309b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns a resource ID representing an image which should be shown when ther's no relevant
310b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * photo is available.
311b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
3124db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @DrawableRes int getDefaultPhotoResId() {
313b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return R.drawable.ic_contact_picture;
314b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
315b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
316b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
317b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns an id for TextView in an item View for showing a display name. By default
318b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * {@link android.R.id#title} is returned.
319b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
3204db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @IdRes int getDisplayNameResId() {
321b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return android.R.id.title;
322b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
323b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
324b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
325b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns an id for TextView in an item View for showing a destination
326b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * (an email address or a phone number).
327b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * By default {@link android.R.id#text1} is returned.
328b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
3294db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @IdRes int getDestinationResId() {
330b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return android.R.id.text1;
331b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
332b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
333b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
334b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns an id for TextView in an item View for showing the type of the destination.
335b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * By default {@link android.R.id#text2} is returned.
336b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
3374db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @IdRes int getDestinationTypeResId() {
338b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return android.R.id.text2;
339b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
340b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
341b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
342b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * Returns an id for ImageView in an item View for showing photo image for a person. In default
343b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * {@link android.R.id#icon} is returned.
344b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
3454db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @IdRes int getPhotoResId() {
346b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        return android.R.id.icon;
347b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
348b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
349b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    /**
3504db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao     * Returns an id for ImageView in an item View for showing the delete button. In default
3514db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao     * {@link android.R.id#icon1} is returned.
3524db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao     */
3534db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    protected @IdRes int getDeleteResId() { return android.R.id.icon1; }
3544db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
3554db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    /**
356e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * Given a constraint and results, tries to find the constraint in those results, one at a time.
357e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * A foreground font color style will be applied to the section that matches the constraint. As
358e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * soon as a match has been found, no further matches are attempted.
359e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     *
360e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * @param constraint A string that we will attempt to find within the results.
361e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * @param results Strings that may contain the constraint. The order given is the order used to
362e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     *     search for the constraint.
363e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     *
364e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     * @return An array of CharSequences, the length determined by the length of results. Each
365e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     *     CharSequence will either be a styled SpannableString or just the input String.
366e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy     */
367e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy    protected CharSequence[] getStyledResults(@Nullable String constraint, String... results) {
368e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        if (isAllWhitespace(constraint)) {
369e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            return results;
370e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        }
371e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
372e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        CharSequence[] styledResults = new CharSequence[results.length];
373e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        boolean foundMatch = false;
374e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        for (int i = 0; i < results.length; i++) {
375e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            String result = results[i];
376e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            if (result == null) {
377e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                continue;
378e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            }
379e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
380e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            if (!foundMatch) {
381e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                int index = result.toLowerCase().indexOf(constraint.toLowerCase());
382e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                if (index != -1) {
383e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    SpannableStringBuilder styled = SpannableStringBuilder.valueOf(result);
384e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    ForegroundColorSpan highlightSpan =
385e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                            new ForegroundColorSpan(mContext.getResources().getColor(
386e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                                    R.color.chips_dropdown_text_highlighted));
387e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    styled.setSpan(highlightSpan,
388e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                            index, index + constraint.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
389e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    styledResults[i] = styled;
390e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    foundMatch = true;
391e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                    continue;
392e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                }
393e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            }
394e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            styledResults[i] = result;
395e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        }
396e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        return styledResults;
397e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy    }
398e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
399e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy    private static boolean isAllWhitespace(@Nullable String string) {
400e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        if (TextUtils.isEmpty(string)) {
401e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            return true;
402e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        }
403e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
404e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        for (int i = 0; i < string.length(); ++i) {
405e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            if (!Character.isWhitespace(string.charAt(i))) {
406e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy                return false;
407e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy            }
408e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        }
409e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
410e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy        return true;
411e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy    }
412e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy
413e5d17d57be3b89a6adb7d429a4cb3cb1fbb422ffScott Kennedy    /**
414b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * A holder class the view. Uses the getters in DropdownChipLayouter to find the id of the
415b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     * corresponding views.
416b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin     */
417b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    protected class ViewHolder {
418b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        public final TextView displayNameView;
419b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        public final TextView destinationView;
420b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        public final TextView destinationTypeView;
421b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        public final ImageView imageView;
4224db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        public final ImageView deleteView;
423b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao        public final View topDivider;
4246f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy        public final View bottomDivider;
425b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
426b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        public ViewHolder(View view) {
427b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            displayNameView = (TextView) view.findViewById(getDisplayNameResId());
428b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            destinationView = (TextView) view.findViewById(getDestinationResId());
429b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            destinationTypeView = (TextView) view.findViewById(getDestinationTypeResId());
430b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin            imageView = (ImageView) view.findViewById(getPhotoResId());
4314db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao            deleteView = (ImageView) view.findViewById(getDeleteResId());
432b58c9a621a250c6119be2d5a77164b940a8559b0Jin Cao            topDivider = view.findViewById(R.id.chip_autocomplete_top_divider);
4336f86e3b4ab4137d43769d78abd9a45ed84e6e50dScott Kennedy            bottomDivider = view.findViewById(R.id.chip_autocomplete_bottom_divider);
434b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        }
435b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    }
436b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin}
437