1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.messaging.ui.contact; 17 18 import android.content.Context; 19 import android.database.Cursor; 20 import android.net.Uri; 21 import android.provider.ContactsContract.CommonDataKinds.Phone; 22 import android.util.AttributeSet; 23 import android.view.View; 24 import android.view.View.OnClickListener; 25 import android.widget.ImageView; 26 import android.widget.LinearLayout; 27 import android.widget.TextView; 28 29 import com.android.ex.chips.RecipientEntry; 30 import com.android.messaging.R; 31 import com.android.messaging.datamodel.DataModel; 32 import com.android.messaging.datamodel.data.ContactListItemData; 33 import com.android.messaging.datamodel.data.ParticipantData; 34 import com.android.messaging.ui.ContactIconView; 35 import com.android.messaging.util.Assert; 36 import com.android.messaging.util.AvatarUriUtil; 37 import com.google.common.annotations.VisibleForTesting; 38 39 /** 40 * The view for a single entry in a contact list. 41 */ 42 public class ContactListItemView extends LinearLayout implements OnClickListener { 43 public interface HostInterface { onContactListItemClicked(ContactListItemData item, ContactListItemView view)44 void onContactListItemClicked(ContactListItemData item, ContactListItemView view); isContactSelected(ContactListItemData item)45 boolean isContactSelected(ContactListItemData item); 46 } 47 48 @VisibleForTesting 49 final ContactListItemData mData; 50 private TextView mContactNameTextView; 51 private TextView mContactDetailsTextView; 52 private TextView mContactDetailTypeTextView; 53 private TextView mAlphabetHeaderTextView; 54 private ContactIconView mContactIconView; 55 private ImageView mContactCheckmarkView; 56 private ImageView mWorkProfileIcon; 57 private HostInterface mHostInterface; 58 private boolean mShouldShowAlphabetHeader; 59 ContactListItemView(final Context context, final AttributeSet attrs)60 public ContactListItemView(final Context context, final AttributeSet attrs) { 61 super(context, attrs); 62 mData = DataModel.get().createContactListItemData(); 63 } 64 65 @Override onFinishInflate()66 protected void onFinishInflate () { 67 mContactNameTextView = (TextView) findViewById(R.id.contact_name); 68 mContactDetailsTextView = (TextView) findViewById(R.id.contact_details); 69 mContactDetailTypeTextView = (TextView) findViewById(R.id.contact_detail_type); 70 mAlphabetHeaderTextView = (TextView) findViewById(R.id.alphabet_header); 71 mContactIconView = (ContactIconView) findViewById(R.id.contact_icon); 72 mContactCheckmarkView = (ImageView) findViewById(R.id.contact_checkmark); 73 mWorkProfileIcon = (ImageView) findViewById(R.id.work_profile_icon); 74 } 75 76 /** 77 * Fills in the data associated with this view by binding to a contact cursor provided by 78 * ContactUtil. 79 * @param cursor the contact cursor. 80 * @param hostInterface host interface to this view. 81 * @param shouldShowAlphabetHeader whether an alphabetical header should shown on the side 82 * of this view. If {@code headerLabel} is empty, we will still leave space for it. 83 * @param headerLabel the alphabetical header on the side of this view, if it should be shown. 84 */ bind(final Cursor cursor, final HostInterface hostInterface, final boolean shouldShowAlphabetHeader, final String headerLabel)85 public void bind(final Cursor cursor, final HostInterface hostInterface, 86 final boolean shouldShowAlphabetHeader, final String headerLabel) { 87 mData.bind(cursor, headerLabel); 88 mHostInterface = hostInterface; 89 mShouldShowAlphabetHeader = shouldShowAlphabetHeader; 90 setOnClickListener(this); 91 updateViewAppearance(); 92 } 93 94 /** 95 * Binds a RecipientEntry. This is used by the chips text view's dropdown layout. 96 * @param recipientEntry the source RecipientEntry provided by ContactDropdownLayouter, which 97 * was in turn directly from one of the existing chips, or from filtered results 98 * generated by ContactRecipientAdapter. 99 * @param styledName display name where the portion that matches the search text is bold. 100 * @param styledDestination number where the portion that matches the search text is bold. 101 * @param hostInterface host interface to this view. 102 * @param isSingleRecipient whether this item is shown as the only line item in the single 103 * recipient drop down from the chips view. If this is the case, we always show the 104 * contact avatar even if it's not a first-level entry. 105 * @param isWorkContact whether the contact is in managed profile. 106 */ bind(final RecipientEntry recipientEntry, final CharSequence styledName, final CharSequence styledDestination, final HostInterface hostInterface, final boolean isSingleRecipient, final boolean isWorkContact)107 public void bind(final RecipientEntry recipientEntry, final CharSequence styledName, 108 final CharSequence styledDestination, final HostInterface hostInterface, 109 final boolean isSingleRecipient, final boolean isWorkContact) { 110 mData.bind(recipientEntry, styledName, styledDestination, isSingleRecipient, isWorkContact); 111 mHostInterface = hostInterface; 112 mShouldShowAlphabetHeader = false; 113 updateViewAppearance(); 114 } 115 updateViewAppearance()116 private void updateViewAppearance() { 117 mContactNameTextView.setText(mData.getDisplayName()); 118 mContactDetailsTextView.setText(mData.getDestination()); 119 mContactDetailTypeTextView.setText(Phone.getTypeLabel(getResources(), 120 mData.getDestinationType(), mData.getDestinationLabel())); 121 final RecipientEntry recipientEntry = mData.getRecipientEntry(); 122 final String destinationString = String.valueOf(mData.getDestination()); 123 if (mData.getIsSimpleContactItem()) { 124 // This is a special number-with-avatar type of contact (for unknown contact chips 125 // and for direct "send to destination" item). In this case, make sure we only show 126 // the display name (phone number) and the avatar and hide everything else. 127 final Uri avatarUri = AvatarUriUtil.createAvatarUri( 128 ParticipantData.getFromRecipientEntry(recipientEntry)); 129 mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(), 130 mData.getLookupKey(), destinationString); 131 mContactIconView.setVisibility(VISIBLE); 132 mContactCheckmarkView.setVisibility(GONE); 133 mContactDetailTypeTextView.setVisibility(GONE); 134 mContactDetailsTextView.setVisibility(GONE); 135 mContactNameTextView.setVisibility(VISIBLE); 136 } else if (mData.getIsFirstLevel()) { 137 final Uri avatarUri = AvatarUriUtil.createAvatarUri( 138 ParticipantData.getFromRecipientEntry(recipientEntry)); 139 mContactIconView.setImageResourceUri(avatarUri, mData.getContactId(), 140 mData.getLookupKey(), destinationString); 141 mContactIconView.setVisibility(VISIBLE); 142 mContactNameTextView.setVisibility(VISIBLE); 143 final boolean isSelected = mHostInterface.isContactSelected(mData); 144 setSelected(isSelected); 145 mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE); 146 mContactDetailsTextView.setVisibility(VISIBLE); 147 mContactDetailTypeTextView.setVisibility(VISIBLE); 148 } else { 149 mContactIconView.setImageResourceUri(null); 150 mContactIconView.setVisibility(INVISIBLE); 151 mContactNameTextView.setVisibility(GONE); 152 final boolean isSelected = mHostInterface.isContactSelected(mData); 153 setSelected(isSelected); 154 mContactCheckmarkView.setVisibility(isSelected ? VISIBLE : GONE); 155 mContactDetailsTextView.setVisibility(VISIBLE); 156 mContactDetailTypeTextView.setVisibility(VISIBLE); 157 } 158 if (mData.getIsWorkContact()) { 159 mWorkProfileIcon.setVisibility(VISIBLE); 160 } else { 161 mWorkProfileIcon.setVisibility(GONE); 162 } 163 if (mShouldShowAlphabetHeader) { 164 mAlphabetHeaderTextView.setVisibility(VISIBLE); 165 mAlphabetHeaderTextView.setText(mData.getAlphabetHeader()); 166 } else { 167 mAlphabetHeaderTextView.setVisibility(GONE); 168 } 169 } 170 171 /** 172 * {@inheritDoc} from OnClickListener 173 */ 174 @Override onClick(final View v)175 public void onClick(final View v) { 176 Assert.isTrue(v == this); 177 Assert.isTrue(mHostInterface != null); 178 mHostInterface.onContactListItemClicked(mData, this); 179 } 180 setImageClickHandlerDisabled(final boolean isHandlerDisabled)181 public void setImageClickHandlerDisabled(final boolean isHandlerDisabled) { 182 mContactIconView.setImageClickHandlerDisabled(isHandlerDisabled); 183 } 184 } 185