179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan/* 279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Copyright (C) 2011 The Android Open Source Project 379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * 479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Licensed under the Apache License, Version 2.0 (the "License"); 579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * you may not use this file except in compliance with the License. 679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * You may obtain a copy of the License at 779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * 879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * http://www.apache.org/licenses/LICENSE-2.0 979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * 1079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Unless required by applicable law or agreed to in writing, software 1179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * distributed under the License is distributed on an "AS IS" BASIS, 1279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * See the License for the specific language governing permissions and 1479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * limitations under the License. 1579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 1679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 1779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanpackage com.android.contacts.detail; 1879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 19fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.google.common.collect.Iterables; 20fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwell 21fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.R; 22fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.Contact; 23fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.RawContact; 24fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.dataitem.DataItem; 25fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.dataitem.OrganizationDataItem; 26fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.preference.ContactsPreferences; 27fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.util.MoreMath; 28fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwell 2979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.Context; 3065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager; 3165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager.NameNotFoundException; 3265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources; 3365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources.NotFoundException; 3465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.graphics.drawable.Drawable; 353915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.net.Uri; 3679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract.DisplayNameSources; 37c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter; 383915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.text.Html; 39c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics; 4079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.text.TextUtils; 4165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.util.Log; 42c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmannimport android.view.MenuItem; 4379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.view.View; 4479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.ImageView; 456c0470e21d8506fb53915df7463634fd47288343Katherine Kuanimport android.widget.ListView; 4679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.TextView; 4779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 483915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport java.util.List; 493915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 5079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan/** 5179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * This class contains utility methods to bind high-level contact details 5279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * (meaning name, phonetic name, job, and attribution) from a 53851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * {@link Contact} data object to appropriate {@link View}s. 5479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 55333091ae754ddfc25714c14b9b89534be24379f9Paul Soulospublic class ContactDisplayUtils { 56333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos private static final String TAG = "ContactDisplayUtils"; 57c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance(); 5865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 59f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki /** 60599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki * Returns the display name of the contact, using the current display order setting. 61599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki * Returns res/string/missing_name if there is no display name. 6279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 63851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static CharSequence getDisplayName(Context context, Contact contactData) { 6479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan ContactsPreferences prefs = new ContactsPreferences(context); 65e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert final CharSequence displayName = contactData.getDisplayName(); 66c9bb2179ab321461f88f54d49e9d41f2f6b19fe3Yorke Lee if (prefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY) { 67e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert if (!TextUtils.isEmpty(displayName)) { 68c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell if (contactData.getDisplayNameSource() == DisplayNameSources.PHONE) { 69c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell return sBidiFormatter.unicodeWrap( 70c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell displayName.toString(), TextDirectionHeuristics.LTR); 71c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell } 72e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert return displayName; 7379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 7481281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } else { 75e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert final CharSequence altDisplayName = contactData.getAltDisplayName(); 76e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert if (!TextUtils.isEmpty(altDisplayName)) { 77e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert return altDisplayName; 78e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert } 7979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 80e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert return context.getResources().getString(R.string.missing_name); 8179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 8279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 8379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 8479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Returns the phonetic name of the contact or null if there isn't one. 8579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 86851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static String getPhoneticName(Context context, Contact contactData) { 8779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String phoneticName = contactData.getPhoneticName(); 8879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(phoneticName)) { 8979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return phoneticName; 9079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 9179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 9279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 9379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 9479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 95afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan * Returns the attribution string for the contact, which may specify the contact directory that 96afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan * the contact came from. Returns null if there is none applicable. 9779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 98851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static String getAttribution(Context context, Contact contactData) { 99afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan if (contactData.isDirectoryEntry()) { 10079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String directoryDisplayName = contactData.getDirectoryDisplayName(); 10179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String directoryType = contactData.getDirectoryType(); 1022e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee final String displayName; 1032e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee if (!TextUtils.isEmpty(directoryDisplayName)) { 1042e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee displayName = directoryDisplayName; 1052e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } else if (!TextUtils.isEmpty(directoryType)) { 1062e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee displayName = directoryType; 1072e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } else { 1082e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee return null; 1092e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee } 11079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return context.getString(R.string.contact_directory_description, displayName); 11179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 11279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 11379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 11479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 11579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 11679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Returns the organization of the contact. If several organizations are given, 11779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * the first one is used. Returns null if not applicable. 11879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 119851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static String getCompany(Context context, Contact contactData) { 12079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final boolean displayNameIsOrganization = contactData.getDisplayNameSource() 12179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan == DisplayNameSources.ORGANIZATION; 122851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : contactData.getRawContacts()) { 123851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : Iterables.filter( 124851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu rawContact.getDataItems(), OrganizationDataItem.class)) { 125851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu OrganizationDataItem organization = (OrganizationDataItem) dataItem; 126851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String company = organization.getCompany(); 127851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String title = organization.getTitle(); 128851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String combined; 129851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // We need to show company and title in a combined string. However, if the 130851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // DisplayName is already the organization, it mirrors company or (if company 131851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu // is empty title). Make sure we don't show what's already shown as DisplayName 132851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (TextUtils.isEmpty(company)) { 133851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu combined = displayNameIsOrganization ? null : title; 134851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu } else { 135851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (TextUtils.isEmpty(title)) { 136851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu combined = displayNameIsOrganization ? null : company; 13779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 138851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (displayNameIsOrganization) { 139851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu combined = title; 14079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 141851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu combined = context.getString( 142851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu R.string.organization_company_and_title, 143851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu company, title); 14479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 14579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 146851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu } 14779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 148851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu if (!TextUtils.isEmpty(combined)) { 149851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu return combined; 15079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 15179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 15279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 15379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 15479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 15579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 15679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 15779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the starred state of this contact. 15879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 159c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann public static void configureStarredImageView(ImageView starredView, boolean isDirectoryEntry, 160c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann boolean isUserProfile, boolean isStarred) { 16179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // Check if the starred state should be visible 162c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann if (!isDirectoryEntry && !isUserProfile) { 16379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan starredView.setVisibility(View.VISIBLE); 164c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann final int resId = isStarred 165c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann ? R.drawable.btn_star_on_normal_holo_light 166c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann : R.drawable.btn_star_off_normal_holo_light; 167c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredView.setImageResource(resId); 168c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredView.setTag(isStarred); 169c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredView.setContentDescription(starredView.getResources().getString( 170c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann isStarred ? R.string.menu_removeStar : R.string.menu_addStar)); 17179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 17279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan starredView.setVisibility(View.GONE); 173c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann } 174c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann } 175c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann 176c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann /** 177c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann * Sets the starred state of this contact. 178c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann */ 179c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann public static void configureStarredMenuItem(MenuItem starredMenuItem, boolean isDirectoryEntry, 180c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann boolean isUserProfile, boolean isStarred) { 181c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann // Check if the starred state should be visible 182c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann if (!isDirectoryEntry && !isUserProfile) { 183c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredMenuItem.setVisible(true); 184c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann final int resId = isStarred 185d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ? R.drawable.ic_star_24dp 186d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell : R.drawable.ic_star_outline_24dp; 187c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredMenuItem.setIcon(resId); 188c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredMenuItem.setChecked(isStarred); 189c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredMenuItem.setTitle(isStarred ? R.string.menu_removeStar : R.string.menu_addStar); 190c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann } else { 191c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann starredMenuItem.setVisible(false); 19279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 19379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 19479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 19579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 1962eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Sets the display name of this contact to the given {@link TextView}. If 1972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * there is none, then set the view to gone. 1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 199851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static void setDisplayName(Context context, Contact contactData, TextView textView) { 2002eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 2012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan setDataOrHideIfNone(getDisplayName(context, contactData), textView); 2042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 2062eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 2072eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Sets the company and job title of this contact to the given {@link TextView}. If 2082eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * there is none, then set the view to gone. 2092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 210851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static void setCompanyName(Context context, Contact contactData, TextView textView) { 2112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 2122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 2132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan setDataOrHideIfNone(getCompany(context, contactData), textView); 2152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 2162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 2172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 21879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the phonetic name of this contact to the given {@link TextView}. If 21979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * there is none, then set the view to gone. 22079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 221851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static void setPhoneticName(Context context, Contact contactData, TextView textView) { 2222eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 2232eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 2242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 22579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan setDataOrHideIfNone(getPhoneticName(context, contactData), textView); 22679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 22779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 22879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 22979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the attribution contact to the given {@link TextView}. If 23079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * there is none, then set the view to gone. 23179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 232851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public static void setAttribution(Context context, Contact contactData, TextView textView) { 2332eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 2342eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 2352eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 23679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan setDataOrHideIfNone(getAttribution(context, contactData), textView); 23779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 23879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 23979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 24079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Helper function to display the given text in the {@link TextView} or 24179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * hides the {@link TextView} if the text is empty or null. 24279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 24379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan private static void setDataOrHideIfNone(CharSequence textToDisplay, TextView textView) { 24479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(textToDisplay)) { 24579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setText(textToDisplay); 24679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setVisibility(View.VISIBLE); 24779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 24879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setText(null); 24979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setVisibility(View.GONE); 25079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 25179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 25279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 253da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki private static Html.ImageGetter sImageGetter; 254da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki 255da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki public static Html.ImageGetter getImageGetter(Context context) { 256da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki if (sImageGetter == null) { 257da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki sImageGetter = new DefaultImageGetter(context.getPackageManager()); 258da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki } 259da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki return sImageGetter; 260da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki } 261da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki 26265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Fetcher for images from resources to be included in HTML text. */ 26365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private static class DefaultImageGetter implements Html.ImageGetter { 26465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** The scheme used to load resources. */ 26565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private static final String RES_SCHEME = "res"; 26665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 26765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private final PackageManager mPackageManager; 26865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 26965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda public DefaultImageGetter(PackageManager packageManager) { 27065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda mPackageManager = packageManager; 27165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 27265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 27365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda @Override 27465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda public Drawable getDrawable(String source) { 27565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // Returning null means that a default image will be used. 27665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Uri uri; 27765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 27865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda uri = Uri.parse(source); 27965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (Throwable e) { 28065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 28165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 28265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 28365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (!RES_SCHEME.equals(uri.getScheme())) { 28465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Image source does not correspond to a resource: " + source); 28565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 28665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 28765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // The URI authority represents the package name. 28865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda String packageName = uri.getAuthority(); 28965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 29065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Resources resources = getResourcesForResourceName(packageName); 29165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (resources == null) { 29265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 29365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 29465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 29565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 29665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda List<String> pathSegments = uri.getPathSegments(); 29765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (pathSegments.size() != 1) { 29865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 29965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 30065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 30165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 30265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda final String name = pathSegments.get(0); 30365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda final int resId = resources.getIdentifier(name, "drawable", packageName); 30465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 30565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (resId == 0) { 30665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // Use the default image icon in this case. 30765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Cannot resolve resource identifier: " + source); 30865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 30965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 31065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 31165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 31265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return getResourceDrawable(resources, resId); 31365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (NotFoundException e) { 31465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Resource not found: " + source, e); 31565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 31665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 31765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 31865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 31965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Returns the drawable associated with the given id. */ 32065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private Drawable getResourceDrawable(Resources resources, int resId) 32165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda throws NotFoundException { 32265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Drawable drawable = resources.getDrawable(resId); 32365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 32465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return drawable; 32565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 32665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 32765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Returns the {@link Resources} of the package of the given resource name. */ 32865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private Resources getResourcesForResourceName(String packageName) { 32965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 33065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return mPackageManager.getResourcesForApplication(packageName); 33165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (NameNotFoundException e) { 33265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not find package: " + packageName); 33365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 33465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 33565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 33665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 33725594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan 33825594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan /** 33925594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan * Sets an alpha value on the view. 34025594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan */ 34125594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan public static void setAlphaOnViewBackground(View view, float alpha) { 34225594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan if (view != null) { 34325594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan // Convert alpha layer to a black background HEX color with an alpha value for better 34425594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan // performance (i.e. use setBackgroundColor() instead of setAlpha()) 345187c8167d77687fbc04237c9ac1e87564b2d5f33Josh Gargus view.setBackgroundColor((int) (MoreMath.clamp(alpha, 0.0f, 1.0f) * 255) << 24); 34625594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan } 34725594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan } 3486c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 3496c0470e21d8506fb53915df7463634fd47288343Katherine Kuan /** 3506c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Returns the top coordinate of the first item in the {@link ListView}. If the first item 3516c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * in the {@link ListView} is not visible or there are no children in the list, then return 3526c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the 3536c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * list cannot have a positive offset. 3546c0470e21d8506fb53915df7463634fd47288343Katherine Kuan */ 3556c0470e21d8506fb53915df7463634fd47288343Katherine Kuan public static int getFirstListItemOffset(ListView listView) { 3566c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView == null || listView.getChildCount() == 0 || 3576c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.getFirstVisiblePosition() != 0) { 3586c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return Integer.MIN_VALUE; 3596c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 3606c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return listView.getChildAt(0).getTop(); 3616c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 3626c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 3636c0470e21d8506fb53915df7463634fd47288343Katherine Kuan /** 3646c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Tries to scroll the first item in the list to the given offset (this can be a no-op if the 3656c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * list is already in the correct position). 3666c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * @param listView that should be scrolled 3676c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * @param offset which should be <= 0 3686c0470e21d8506fb53915df7463634fd47288343Katherine Kuan */ 3696c0470e21d8506fb53915df7463634fd47288343Katherine Kuan public static void requestToMoveToOffset(ListView listView, int offset) { 3706c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // We try to offset the list if the first item in the list is showing (which is presumed 3716c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // to have a larger height than the desired offset). If the first item in the list is not 3726c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // visible, then we simply do not scroll the list at all (since it can get complicated to 3736c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // compute how many items in the list will equal the given offset). Potentially 3746c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // some animation elsewhere will make the transition smoother for the user to compensate 3756c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // for this simplification. 3766c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView == null || listView.getChildCount() == 0 || 3776c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.getFirstVisiblePosition() != 0 || offset > 0) { 3786c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return; 3796c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 3806c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 3816c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // As an optimization, check if the first item is already at the given offset. 3826c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView.getChildAt(0).getTop() == offset) { 3836c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return; 3846c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 3856c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 3866c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.setSelectionFromTop(0, offset); 3876c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 38822cb663a251af60bc6beeb1954568c8e6a4c34e9Flavio Lerda} 389