1476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer/* 2476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * Copyright (C) 2017 The Android Open Source Project 3476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * 4476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License"); 5476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * you may not use this file except in compliance with the License. 6476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * You may obtain a copy of the License at 7476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * 8476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * http://www.apache.org/licenses/LICENSE-2.0 9476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * 10476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * Unless required by applicable law or agreed to in writing, software 11476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS, 12476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * See the License for the specific language governing permissions and 14476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * limitations under the License. 15476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer */ 16476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerpackage com.android.car.dialer; 17476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 18f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.app.Fragment; 19f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.app.LoaderManager; 20f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.content.CursorLoader; 21f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.content.Intent; 22f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.content.Loader; 23476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.database.Cursor; 24476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.net.Uri; 25476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.os.Bundle; 26476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.provider.ContactsContract; 27f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.support.annotation.ColorInt; 28f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chenimport android.support.annotation.Nullable; 29476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.support.v7.widget.RecyclerView; 30476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.util.Log; 31476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.util.Pair; 32476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.view.LayoutInflater; 33476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.view.View; 34476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.view.ViewGroup; 35476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.widget.ImageView; 36476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport android.widget.TextView; 37476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 38476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport com.android.car.dialer.telecom.TelecomUtils; 39476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport com.android.car.view.PagedListView; 40476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 41476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport java.util.ArrayList; 42476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerimport java.util.List; 43476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 44476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer/** 45476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * A fragment that shows the name of the contact, the photo and all listed phone numbers. It is 46f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen * primarily used to respond to the results of search queries but supplyig it with the content:// 47476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * uri of a contact should work too. 48476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer */ 49476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyerpublic class ContactDetailsFragment extends Fragment 50476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer implements LoaderManager.LoaderCallbacks<Cursor> { 51476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private static final String TAG = "ContactDetailsFragment"; 52f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen private static final String TELEPHONE_URI_PREFIX = "tel:"; 53f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 5417d5ac7d0b429687765e940279726623f5f5f823Anthony Chen private static final int DETAILS_LOADER_QUERY_ID = 1; 5517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen private static final int PHONE_LOADER_QUERY_ID = 2; 56f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 57476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private static final String KEY_URI = "uri"; 58476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 59476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private static final String[] CONTACT_DETAILS_PROJECTION = { 60476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer ContactsContract.Contacts._ID, 61476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer ContactsContract.Contacts.DISPLAY_NAME, 62476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer ContactsContract.Contacts.PHOTO_URI, 63476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer ContactsContract.Contacts.HAS_PHONE_NUMBER 64476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer }; 65476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 66476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private PagedListView mListView; 67f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen private List<RecyclerView.OnScrollListener> mOnScrollListeners = new ArrayList<>(); 68476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 69f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public static ContactDetailsFragment newInstance(Uri uri, 70f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Nullable RecyclerView.OnScrollListener listener) { 71476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer ContactDetailsFragment fragment = new ContactDetailsFragment(); 72f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen fragment.addOnScrollListener(listener); 7317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen 74476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Bundle args = new Bundle(); 75476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer args.putParcelable(KEY_URI, uri); 76476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer fragment.setArguments(args); 7717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen 78476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return fragment; 79476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 80476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 81476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 82476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public View onCreateView(LayoutInflater inflater, ViewGroup container, 83476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Bundle savedInstanceState) { 84f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen return inflater.inflate(R.layout.contact_details, container, false); 85f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 86f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 87f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Override 88f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public void onViewCreated(View view, Bundle savedInstanceState) { 89f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mListView = view.findViewById(R.id.list_view); 90f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mListView.setLightMode(); 91f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 92f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen RecyclerView recyclerView = mListView.getRecyclerView(); 93f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen for (RecyclerView.OnScrollListener listener : mOnScrollListeners) { 94f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen recyclerView.addOnScrollListener(listener); 95f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 96f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 97f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mOnScrollListeners.clear(); 98476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 99476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 100476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 101476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public void onActivityCreated(Bundle savedInstanceState) { 102476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer super.onActivityCreated(savedInstanceState); 10317d5ac7d0b429687765e940279726623f5f5f823Anthony Chen getLoaderManager().initLoader(DETAILS_LOADER_QUERY_ID, null, this); 104476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 105476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 106f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen /** 107f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen * Adds a {@link android.support.v7.widget.RecyclerView.OnScrollListener} to be notified when 108f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen * the contact details are scrolled. 109f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen * 110f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen * @see RecyclerView#addOnScrollListener(RecyclerView.OnScrollListener) 111f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen */ 112f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public void addOnScrollListener(RecyclerView.OnScrollListener onScrollListener) { 113f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen // If the view has not been created yet, then queue the setting of the scroll listener. 114f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen if (mListView == null) { 115f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mOnScrollListeners.add(onScrollListener); 116f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen return; 117f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 118f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 119f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mListView.getRecyclerView().addOnScrollListener(onScrollListener); 120f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 121f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 122f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Override 123f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public void onDestroy() { 124f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen // Clear all scroll listeners. 125f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mListView.getRecyclerView().removeOnScrollListener(null); 126f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen super.onDestroy(); 127f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 128f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 129476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 130476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public Loader<Cursor> onCreateLoader(int id, Bundle args) { 131476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (vdebug()) { 132476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Log.d(TAG, "onCreateLoader id=" + id); 133476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 134476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 13517d5ac7d0b429687765e940279726623f5f5f823Anthony Chen if (id != DETAILS_LOADER_QUERY_ID) { 136476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return null; 137476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 138476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 139476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Uri contactUri = getArguments().getParcelable(KEY_URI); 140476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return new CursorLoader(getContext(), contactUri, CONTACT_DETAILS_PROJECTION, 141476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer null /* selection */, null /* selectionArgs */, null /* sortOrder */); 142476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 143476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 144476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 145476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 146476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (vdebug()) { 147476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Log.d(TAG, "onLoadFinished"); 148476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 149476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 150476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (cursor.moveToFirst()) { 151476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer mListView.setAdapter(new ContactDetailsAdapter(cursor)); 152476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 153476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 154476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 155476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 156476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public void onLoaderReset(Loader loader) { } 157476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 158476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private boolean vdebug() { 159476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return Log.isLoggable(TAG, Log.DEBUG); 160476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 161476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 162f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen private class ContactDetailViewHolder extends RecyclerView.ViewHolder { 163476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public View card; 164476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public ImageView leftIcon; 165476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public TextView title; 166476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public TextView text; 167476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public ImageView rightIcon; 168476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 169476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public ContactDetailViewHolder(View v) { 170476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer super(v); 171476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer card = v.findViewById(R.id.card); 172476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer leftIcon = v.findViewById(R.id.icon); 173476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer title = v.findViewById(R.id.title); 174476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer text = v.findViewById(R.id.text); 175476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer rightIcon = v.findViewById(R.id.right_icon); 176476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 177476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 178476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 179f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen private class ContactDetailsAdapter extends RecyclerView.Adapter<ContactDetailViewHolder> 180476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer implements PagedListView.ItemCap { 181476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 182476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private static final int ID_HEADER = 1; 183476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private static final int ID_CONTENT = 2; 184476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 185476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private final String mContactName; 186f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @ColorInt private int mIconTint; 187476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 188476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private List<Pair<String, String>> mPhoneNumbers = new ArrayList<>(); 189476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 190476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public ContactDetailsAdapter(Cursor cursor) { 191476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer super(); 192476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 193f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mIconTint = getContext().getColor(R.color.contact_details_icon_tint); 194f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 195476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int idColIdx = cursor.getColumnIndex(ContactsContract.Contacts._ID); 196476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer String contactId = cursor.getString(idColIdx); 197476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int nameColIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); 198476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer mContactName = cursor.getString(nameColIdx); 199476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int hasPhoneColIdx = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER); 200476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer boolean hasPhoneNumber = Integer.parseInt(cursor.getString(hasPhoneColIdx)) > 0; 201476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 202476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (!hasPhoneNumber) { 203476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return; 204476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 205476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 206476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // Fetch the phone number from the contacts db using another loader. 20717d5ac7d0b429687765e940279726623f5f5f823Anthony Chen getLoaderManager().initLoader(PHONE_LOADER_QUERY_ID, null, 208476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer new LoaderManager.LoaderCallbacks<Cursor>() { 209f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Override 210f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public Loader<Cursor> onCreateLoader(int id, Bundle args) { 211f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen return new CursorLoader(getContext(), 212f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 213f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen null, /* All columns **/ 214f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", 215f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen new String[] { contactId }, 216f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen null /* sortOrder */); 217476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 218476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 219f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 220f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen while (cursor.moveToNext()) { 221f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen int typeColIdx = cursor.getColumnIndex( 222f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen ContactsContract.CommonDataKinds.Phone.TYPE); 223f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen int type = cursor.getInt(typeColIdx); 224f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen int numberColIdx = cursor.getColumnIndex( 225f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen ContactsContract.CommonDataKinds.Phone.NUMBER); 226f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen String number = cursor.getString(numberColIdx); 227f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen String numberType; 228f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen switch (type) { 229f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen case ContactsContract.CommonDataKinds.Phone.TYPE_HOME: 230f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen numberType = getString(R.string.type_home); 231f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen break; 232f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen case ContactsContract.CommonDataKinds.Phone.TYPE_WORK: 233f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen numberType = getString(R.string.type_work); 234f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen break; 235f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE: 236f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen numberType = getString(R.string.type_mobile); 237f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen break; 238f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen default: 239f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen numberType = getString(R.string.type_other); 240f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 241f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen mPhoneNumbers.add(new Pair<>(numberType, 242f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen TelecomUtils.getFormattedNumber(getContext(), number))); 243f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen notifyItemInserted(mPhoneNumbers.size()); 244f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 245f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen notifyDataSetChanged(); 246f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen } 247f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen 248f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen public void onLoaderReset(Loader loader) { } 249f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen }); 250476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 251476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 252476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer /** 253476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * Appropriately sets the background for the View that is being bound. This method will 254476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer * allow for rounded corners on either the top or bottom of a card. 255476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer */ 256476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer private void setBackground(ContactDetailViewHolder viewHolder) { 257476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int itemCount = getItemCount(); 258476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int adapterPosition = viewHolder.getAdapterPosition(); 259476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 260476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (itemCount == 1) { 261476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // Only element - all corners are rounded 262476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.card.setBackgroundResource( 263476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer R.drawable.car_card_rounded_top_bottom_background); 264476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } else if (adapterPosition == 0) { 265476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // First element gets rounded top 266476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.card.setBackgroundResource(R.drawable.car_card_rounded_top_background); 267476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } else if (adapterPosition == itemCount - 1) { 268476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // Last one has a rounded bottom 269476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.card.setBackgroundResource( 270476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer R.drawable.car_card_rounded_bottom_background); 271476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } else { 272476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // Middle have no rounded corners 273476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.card.setBackgroundResource(R.color.car_card); 274476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 275476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 276476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 277476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 278476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public int getItemViewType(int position) { 279476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return position == 0 ? ID_HEADER : ID_CONTENT; 280476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 281476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 282476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 283476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public void setMaxItems(int maxItems) { 284476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer // Ignore. 285476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 286476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 287476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer @Override 288476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public int getItemCount() { 289476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return mPhoneNumbers.size() + 1; // +1 for the header row. 290476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 291476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 292f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Override 293476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public ContactDetailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 294476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer int layoutResId; 295476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer switch (viewType) { 296476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer case ID_HEADER: 297476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer layoutResId = R.layout.contact_detail_name_image; 298476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer break; 299476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer case ID_CONTENT: 300476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer layoutResId = R.layout.contact_details_number; 301476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer break; 302476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer default: 303476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Log.e(TAG, "Unknown view type " + viewType); 304476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return null; 305476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 306476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 307476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer View view = LayoutInflater.from(parent.getContext()).inflate(layoutResId, null); 308476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return new ContactDetailViewHolder(view); 309476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 310476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer 311f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen @Override 312476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer public void onBindViewHolder(ContactDetailViewHolder viewHolder, int position) { 313476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer switch (viewHolder.getItemViewType()) { 314476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer case ID_HEADER: 315476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.title.setText(mContactName); 316476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer if (!mPhoneNumbers.isEmpty()) { 317476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer String firstNumber = mPhoneNumbers.get(0).second; 318476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer TelecomUtils.setContactBitmapAsync(getContext(), viewHolder.rightIcon, 319476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer mContactName, firstNumber); 320476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 321962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer // Just in case a viewholder object gets recycled. 322962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer viewHolder.card.setOnClickListener(null); 323476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer break; 324476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer case ID_CONTENT: 325476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Pair<String, String> data = mPhoneNumbers.get(position - 1); 326962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer viewHolder.title.setText(data.first); // Type. 327962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer viewHolder.text.setText(data.second); // Number. 328476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer viewHolder.leftIcon.setImageResource(R.drawable.ic_phone); 329f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen viewHolder.leftIcon.setColorFilter(mIconTint); 330962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer viewHolder.card.setOnClickListener(v -> { 331f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen Intent callIntent = new Intent(Intent.ACTION_CALL); 332f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen callIntent.setData(Uri.parse(TELEPHONE_URI_PREFIX + data.second)); 333f7ed46be024b7cfb448f93d71f235b30f72aa1eeAnthony Chen getContext().startActivity(callIntent); 334962fa010f1b1ab57477645ce65a7540d167cf788Rakesh Iyer }); 335476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer break; 336476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer default: 337476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer Log.e(TAG, "Unknown view type " + viewHolder.getItemViewType()); 338476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer return; 339476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 340476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer setBackground(viewHolder); 341476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 342476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer } 343476856e35551612a71a33c0f797d09dc73569f2fRakesh Iyer} 344