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 1979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport com.android.contacts.ContactLoader; 2079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport com.android.contacts.ContactLoader.Result; 213915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport com.android.contacts.ContactPhotoManager; 2279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport com.android.contacts.R; 2379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport com.android.contacts.preference.ContactsPreferences; 2479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport com.android.contacts.util.ContactBadgeUtil; 251b4572ba0ba449a4ed0cc896f5f694f33b43f073Dmitri Plotnikovimport com.android.contacts.util.HtmlUtils; 263915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport com.android.contacts.util.StreamItemEntry; 273915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport com.android.contacts.util.StreamItemPhotoEntry; 285a77a5563706fe1b143d976d1b47abaeb873e138Flavio Lerdaimport com.google.common.annotations.VisibleForTesting; 2979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 30f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onukiimport android.content.ContentUris; 3179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.ContentValues; 3279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.Context; 3379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.Entity; 3479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.Entity.NamedContentValues; 3565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager; 3665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager.NameNotFoundException; 3765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources; 3865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources.NotFoundException; 3979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.graphics.Bitmap; 4079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.graphics.BitmapFactory; 4165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.graphics.drawable.Drawable; 423915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.net.Uri; 4379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract; 4479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract.CommonDataKinds.Organization; 4579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract.Data; 4679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract.DisplayNameSources; 47f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onukiimport android.provider.ContactsContract.StreamItems; 483915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.text.Html; 4965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.text.Html.ImageGetter; 5079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.text.TextUtils; 5165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.util.Log; 523915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.view.LayoutInflater; 5379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.view.View; 543915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.view.ViewGroup; 5579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.view.animation.AccelerateInterpolator; 5679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.view.animation.AlphaAnimation; 5779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.CheckBox; 5879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.ImageView; 593915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.widget.LinearLayout; 606c0470e21d8506fb53915df7463634fd47288343Katherine Kuanimport android.widget.ListView; 6179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.TextView; 6279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 633915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport java.util.List; 643915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 6579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan/** 6679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * This class contains utility methods to bind high-level contact details 6779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * (meaning name, phonetic name, job, and attribution) from a 6879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * {@link ContactLoader.Result} data object to appropriate {@link View}s. 6979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 7079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanpublic class ContactDetailDisplayUtils { 7165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private static final String TAG = "ContactDetailDisplayUtils"; 7265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 7379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan private static final int PHOTO_FADE_IN_ANIMATION_DURATION_MILLIS = 100; 7479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 75f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki /** 76f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki * Tag object used for stream item photos. 77f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki */ 78f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki public static class StreamPhotoTag { 79f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki public final StreamItemEntry streamItem; 80f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki public final StreamItemPhotoEntry streamItemPhoto; 81f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki 82f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki public StreamPhotoTag(StreamItemEntry streamItem, StreamItemPhotoEntry streamItemPhoto) { 83f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki this.streamItem = streamItem; 84f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki this.streamItemPhoto = streamItemPhoto; 85f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki } 86f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki 87f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki public Uri getStreamItemPhotoUri() { 88f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki final Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon(); 89f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki ContentUris.appendId(builder, streamItem.getId()); 90f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki builder.appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY); 91f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki ContentUris.appendId(builder, streamItemPhoto.getId()); 92f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki return builder.build(); 93f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki } 94f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki } 95f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki 9679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan private ContactDetailDisplayUtils() { 9779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // Disallow explicit creation of this class. 9879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 9979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 10079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 101599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki * Returns the display name of the contact, using the current display order setting. 102599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki * Returns res/string/missing_name if there is no display name. 10379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 10479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static CharSequence getDisplayName(Context context, Result contactData) { 10579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan CharSequence displayName = contactData.getDisplayName(); 10679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan CharSequence altDisplayName = contactData.getAltDisplayName(); 10779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan ContactsPreferences prefs = new ContactsPreferences(context); 10879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan CharSequence styledName = ""; 10979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(displayName) && !TextUtils.isEmpty(altDisplayName)) { 11079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (prefs.getDisplayOrder() == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) { 111599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki styledName = displayName; 11279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 113599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki styledName = altDisplayName; 11479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 11581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } else { 11681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan styledName = context.getResources().getString(R.string.missing_name); 11779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 11879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return styledName; 11979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 12079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 12179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 12279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Returns the phonetic name of the contact or null if there isn't one. 12379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 12479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static String getPhoneticName(Context context, Result contactData) { 12579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String phoneticName = contactData.getPhoneticName(); 12679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(phoneticName)) { 12779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return phoneticName; 12879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 12979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 13079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 13179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 13279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 133afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan * Returns the attribution string for the contact, which may specify the contact directory that 134afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan * the contact came from. Returns null if there is none applicable. 13579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 13679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static String getAttribution(Context context, Result contactData) { 137afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan if (contactData.isDirectoryEntry()) { 13879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String directoryDisplayName = contactData.getDirectoryDisplayName(); 13979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String directoryType = contactData.getDirectoryType(); 14079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan String displayName = !TextUtils.isEmpty(directoryDisplayName) 14179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan ? directoryDisplayName 14279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan : directoryType; 14379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return context.getString(R.string.contact_directory_description, displayName); 14479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 14579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 14679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 14779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 14879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 14979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Returns the organization of the contact. If several organizations are given, 15079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * the first one is used. Returns null if not applicable. 15179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 15279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static String getCompany(Context context, Result contactData) { 15379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final boolean displayNameIsOrganization = contactData.getDisplayNameSource() 15479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan == DisplayNameSources.ORGANIZATION; 15579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan for (Entity entity : contactData.getEntities()) { 15679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan for (NamedContentValues subValue : entity.getSubValues()) { 15779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final ContentValues entryValues = subValue.values; 15879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final String mimeType = entryValues.getAsString(Data.MIMETYPE); 15979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 16079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) { 16179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final String company = entryValues.getAsString(Organization.COMPANY); 16279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final String title = entryValues.getAsString(Organization.TITLE); 16379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan final String combined; 16479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // We need to show company and title in a combined string. However, if the 16579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // DisplayName is already the organization, it mirrors company or (if company 16679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // is empty title). Make sure we don't show what's already shown as DisplayName 16779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (TextUtils.isEmpty(company)) { 16879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan combined = displayNameIsOrganization ? null : title; 16979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 17079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (TextUtils.isEmpty(title)) { 17179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan combined = displayNameIsOrganization ? null : company; 17279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 17379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (displayNameIsOrganization) { 17479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan combined = title; 17579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 17679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan combined = context.getString( 17779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan R.string.organization_company_and_title, 17879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan company, title); 17979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 18379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(combined)) { 18479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return combined; 18579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 18979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return null; 19079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 19179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 19279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 19379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the contact photo to display in the given {@link ImageView}. If bitmap is null, the 19479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * default placeholder image is shown. 19579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 19679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static void setPhoto(Context context, Result contactData, ImageView photoView) { 19779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (contactData.isLoadingPhoto()) { 19879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan photoView.setImageBitmap(null); 19979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan return; 20079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 20179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan byte[] photo = contactData.getPhotoBinaryData(); 20279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan Bitmap bitmap = photo != null ? BitmapFactory.decodeByteArray(photo, 0, photo.length) 203ecfc26c3f9495f1a4efed69a1582ff2b0deb2c71Daniel Lehmann : ContactBadgeUtil.loadDefaultAvatarPhoto(context, true, false); 20479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan boolean fadeIn = contactData.isDirectoryEntry(); 20579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (photoView.getDrawable() == null && fadeIn) { 20679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan AlphaAnimation animation = new AlphaAnimation(0, 1); 20779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan animation.setDuration(PHOTO_FADE_IN_ANIMATION_DURATION_MILLIS); 20879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan animation.setInterpolator(new AccelerateInterpolator()); 20979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan photoView.startAnimation(animation); 21079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 21179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan photoView.setImageBitmap(bitmap); 21279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 21379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 21479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 21579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the starred state of this contact. 21679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 21779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static void setStarred(Result contactData, CheckBox starredView) { 21879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan // Check if the starred state should be visible 219ead19c5eafee0ffb43b02a4ae75ac5244ad3f853Isaac Katzenelson if (!contactData.isDirectoryEntry() && !contactData.isUserProfile()) { 22079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan starredView.setVisibility(View.VISIBLE); 22179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan starredView.setChecked(contactData.getStarred()); 22279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 22379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan starredView.setVisibility(View.GONE); 22479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 22579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 22679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 22779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 228d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan * Set the social snippet text. If there isn't one, then set the view to gone. 229d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan */ 2303915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro public static void setSocialSnippet(Context context, Result contactData, TextView statusView, 2313915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro ImageView statusPhotoView) { 232d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan if (statusView == null) { 233d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan return; 234d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan } 2353915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 2367c03fd16d9c6138118b6d236694f650289f27326Makoto Onuki CharSequence snippet = null; 2373915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro String photoUri = null; 2383915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro if (!contactData.getStreamItems().isEmpty()) { 2393915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro StreamItemEntry firstEntry = contactData.getStreamItems().get(0); 2401b4572ba0ba449a4ed0cc896f5f694f33b43f073Dmitri Plotnikov snippet = HtmlUtils.fromHtml(context, firstEntry.getText()); 2413915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro if (!firstEntry.getPhotos().isEmpty()) { 2423915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0); 2433915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro photoUri = firstPhoto.getPhotoUri(); 2443915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 2453915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro // If displaying an image, hide the snippet text. 2463915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro snippet = null; 2473915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } 2483915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } 2493915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro setDataOrHideIfNone(snippet, statusView); 2503915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro if (photoUri != null) { 2513915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro ContactPhotoManager.getInstance(context).loadPhoto( 2523d3a15c465b0c4105148458307a7b50e9b267fd0Makoto Onuki statusPhotoView, Uri.parse(photoUri), true, false, 2533d3a15c465b0c4105148458307a7b50e9b267fd0Makoto Onuki ContactPhotoManager.DEFAULT_BLANK); 2543915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro statusPhotoView.setVisibility(View.VISIBLE); 2553915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } else { 2563915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro statusPhotoView.setVisibility(View.GONE); 2573915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } 258d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan } 259d814e42a6ac71962a6eeb9ce37b4abc2c1205952Katherine Kuan 260a21993720988a5fc0b48594d1ff0ce6f932780b7Flavio Lerda /** Creates the view that represents a stream item. */ 261a21993720988a5fc0b48594d1ff0ce6f932780b7Flavio Lerda public static View createStreamItemView(LayoutInflater inflater, Context context, 262f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki StreamItemEntry streamItem, LinearLayout parent, 263f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki View.OnClickListener photoClickListener) { 264fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda View container = inflater.inflate(R.layout.stream_item_container, parent, false); 265fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda ViewGroup contentTable = (ViewGroup) container.findViewById(R.id.stream_item_content); 2663915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 267fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda ContactPhotoManager contactPhotoManager = ContactPhotoManager.getInstance(context); 2683915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro List<StreamItemPhotoEntry> photos = streamItem.getPhotos(); 269fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda final int photoCount = photos.size(); 270fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda 271be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // This stream item only has text. 272be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan if (photoCount == 0) { 273be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan View textOnlyContainer = inflater.inflate(R.layout.stream_item_row_text, contentTable, 274be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan false); 275be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan addStreamItemText(context, streamItem, textOnlyContainer); 276be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan contentTable.addView(textOnlyContainer); 277be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan } else { 278be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // This stream item has text and photos. Process the photos, two at a time. 279be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan for (int index = 0; index < photoCount; index += 2) { 280be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan final StreamItemPhotoEntry firstPhoto = photos.get(index); 281be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan if (index + 1 < photoCount) { 282be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // Put in two photos, side by side. 283be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan final StreamItemPhotoEntry secondPhoto = photos.get(index + 1); 284be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan View photoContainer = inflater.inflate(R.layout.stream_item_row_two_images, 285be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan contentTable, false); 286be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer, 287be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan R.id.stream_item_first_image, photoClickListener); 288be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan loadPhoto(contactPhotoManager, streamItem, secondPhoto, photoContainer, 289be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan R.id.stream_item_second_image, photoClickListener); 290be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan contentTable.addView(photoContainer); 291be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan } else { 292be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // Put in a single photo 293be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan View photoContainer = inflater.inflate( 294be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan R.layout.stream_item_row_one_image, contentTable, false); 295be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer, 296be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan R.id.stream_item_first_image, photoClickListener); 297be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan contentTable.addView(photoContainer); 298be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan } 2993915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } 3003915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 301be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // Add text, comments, and attribution if applicable 302be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan View textContainer = inflater.inflate(R.layout.stream_item_row_text, contentTable, 303fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda false); 304be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan // Add extra padding between the text and the images 305be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan int extraVerticalPadding = context.getResources().getDimensionPixelSize( 306be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan R.dimen.detail_update_section_between_items_vertical_padding); 307be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan textContainer.setPadding(textContainer.getPaddingLeft(), 308be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan textContainer.getPaddingTop() + extraVerticalPadding, 309be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan textContainer.getPaddingRight(), 310be7a9d511eed5a549226b2e1bc2ebd6f65018c4cKatherine Kuan textContainer.getPaddingBottom()); 311fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda addStreamItemText(context, streamItem, textContainer); 312fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda contentTable.addView(textContainer); 3132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 3143915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 315a21993720988a5fc0b48594d1ff0ce6f932780b7Flavio Lerda if (parent != null) { 316fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda parent.addView(container); 31722cb663a251af60bc6beeb1954568c8e6a4c34e9Flavio Lerda } 31822cb663a251af60bc6beeb1954568c8e6a4c34e9Flavio Lerda 319fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda return container; 320fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda } 321fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda 322f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki /** Loads a photo into an image view. The image view is identified by the given id. */ 323fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda private static void loadPhoto(ContactPhotoManager contactPhotoManager, 324f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki final StreamItemEntry streamItem, final StreamItemPhotoEntry streamItemPhoto, 325f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki View photoContainer, int imageViewId, View.OnClickListener photoClickListener) { 3267b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki final View frame = photoContainer.findViewById(imageViewId); 3277b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki final View pushLayerView = frame.findViewById(R.id.push_layer); 3287b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki final ImageView imageView = (ImageView) frame.findViewById(R.id.image); 329f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki if (photoClickListener != null) { 3307b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setOnClickListener(photoClickListener); 3317b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setTag(new StreamPhotoTag(streamItem, streamItemPhoto)); 3327b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setFocusable(true); 3337b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setEnabled(true); 334f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki } else { 3357b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setOnClickListener(null); 3367b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setTag(null); 3377b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setFocusable(false); 3387b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki // setOnClickListener makes it clickable, so we need to overwrite it 3397b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setClickable(false); 3407b45613a6df9eef617d73c9058ec1fb296142119Makoto Onuki pushLayerView.setEnabled(false); 341f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki } 342ecfc26c3f9495f1a4efed69a1582ff2b0deb2c71Daniel Lehmann contactPhotoManager.loadPhoto(imageView, Uri.parse(streamItemPhoto.getPhotoUri()), true, 3433d3a15c465b0c4105148458307a7b50e9b267fd0Makoto Onuki false, ContactPhotoManager.DEFAULT_BLANK); 3443915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro } 3453915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro 3465a77a5563706fe1b143d976d1b47abaeb873e138Flavio Lerda @VisibleForTesting 347fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda static View addStreamItemText(Context context, StreamItemEntry streamItem, View rootView) { 348fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda TextView htmlView = (TextView) rootView.findViewById(R.id.stream_item_html); 349fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda TextView attributionView = (TextView) rootView.findViewById( 3503915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro R.id.stream_item_attribution); 351fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda TextView commentsView = (TextView) rootView.findViewById(R.id.stream_item_comments); 35265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda ImageGetter imageGetter = new DefaultImageGetter(context.getPackageManager()); 3533ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki 3543ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki // Stream item text 3553ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki setDataOrHideIfNone(HtmlUtils.fromHtml(context, streamItem.getText(), imageGetter, null), 3563ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki htmlView); 3573ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki // Attribution 3583ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki setDataOrHideIfNone(ContactBadgeUtil.getSocialDate(streamItem, context), 3593ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki attributionView); 3603ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki // Comments 3613ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki setDataOrHideIfNone(HtmlUtils.fromHtml(context, streamItem.getComments(), imageGetter, 3623ab9a63014a2d5e097d221b424d6d4809295abd0Makoto Onuki null), commentsView); 363fd43cddee690e84f56163cd1c0899c3200b624e7Flavio Lerda return rootView; 36479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 36579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 36679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 3672eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Sets the display name of this contact to the given {@link TextView}. If 3682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * there is none, then set the view to gone. 3692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 3702eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public static void setDisplayName(Context context, Result contactData, TextView textView) { 3712eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 3722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 3732eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 3742eb969cc399d87b659a45568fa951d394c216917Katherine Kuan setDataOrHideIfNone(getDisplayName(context, contactData), textView); 3752eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 3762eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 3772eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 3782eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * Sets the company and job title of this contact to the given {@link TextView}. If 3792eb969cc399d87b659a45568fa951d394c216917Katherine Kuan * there is none, then set the view to gone. 3802eb969cc399d87b659a45568fa951d394c216917Katherine Kuan */ 3812eb969cc399d87b659a45568fa951d394c216917Katherine Kuan public static void setCompanyName(Context context, Result contactData, TextView textView) { 3822eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 3832eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 3842eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 3852eb969cc399d87b659a45568fa951d394c216917Katherine Kuan setDataOrHideIfNone(getCompany(context, contactData), textView); 3862eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 3872eb969cc399d87b659a45568fa951d394c216917Katherine Kuan 3882eb969cc399d87b659a45568fa951d394c216917Katherine Kuan /** 38979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the phonetic name of this contact to the given {@link TextView}. If 39079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * there is none, then set the view to gone. 39179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 39279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static void setPhoneticName(Context context, Result contactData, TextView textView) { 3932eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 3942eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 3952eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 39679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan setDataOrHideIfNone(getPhoneticName(context, contactData), textView); 39779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 39879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 39979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 40079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Sets the attribution contact to the given {@link TextView}. If 40179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * there is none, then set the view to gone. 40279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 40379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan public static void setAttribution(Context context, Result contactData, TextView textView) { 4042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan if (textView == null) { 4052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan return; 4062eb969cc399d87b659a45568fa951d394c216917Katherine Kuan } 40779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan setDataOrHideIfNone(getAttribution(context, contactData), textView); 40879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 40979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 41079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan /** 41179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Helper function to display the given text in the {@link TextView} or 41279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * hides the {@link TextView} if the text is empty or null. 41379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */ 41479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan private static void setDataOrHideIfNone(CharSequence textToDisplay, TextView textView) { 41579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan if (!TextUtils.isEmpty(textToDisplay)) { 41679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setText(textToDisplay); 41779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setVisibility(View.VISIBLE); 41879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } else { 41979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setText(null); 42079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan textView.setVisibility(View.GONE); 42179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 42279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan } 42379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan 42465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Fetcher for images from resources to be included in HTML text. */ 42565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private static class DefaultImageGetter implements Html.ImageGetter { 42665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** The scheme used to load resources. */ 42765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private static final String RES_SCHEME = "res"; 42865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 42965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private final PackageManager mPackageManager; 43065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 43165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda public DefaultImageGetter(PackageManager packageManager) { 43265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda mPackageManager = packageManager; 43365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 43465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 43565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda @Override 43665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda public Drawable getDrawable(String source) { 43765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // Returning null means that a default image will be used. 43865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Uri uri; 43965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 44065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda uri = Uri.parse(source); 44165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (Throwable e) { 44265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 44365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 44465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 44565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (!RES_SCHEME.equals(uri.getScheme())) { 44665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Image source does not correspond to a resource: " + source); 44765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 44865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 44965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // The URI authority represents the package name. 45065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda String packageName = uri.getAuthority(); 45165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 45265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Resources resources = getResourcesForResourceName(packageName); 45365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (resources == null) { 45465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 45565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 45665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 45765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 45865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda List<String> pathSegments = uri.getPathSegments(); 45965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (pathSegments.size() != 1) { 46065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not parse image source: " + source); 46165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 46265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 46365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 46465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda final String name = pathSegments.get(0); 46565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda final int resId = resources.getIdentifier(name, "drawable", packageName); 46665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 46765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda if (resId == 0) { 46865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda // Use the default image icon in this case. 46965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Cannot resolve resource identifier: " + source); 47065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 47165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 47265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 47365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 47465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return getResourceDrawable(resources, resId); 47565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (NotFoundException e) { 47665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Resource not found: " + source, e); 47765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 47865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 47965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 48065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 48165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Returns the drawable associated with the given id. */ 48265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private Drawable getResourceDrawable(Resources resources, int resId) 48365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda throws NotFoundException { 48465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Drawable drawable = resources.getDrawable(resId); 48565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 48665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return drawable; 48765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 48865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda 48965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda /** Returns the {@link Resources} of the package of the given resource name. */ 49065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda private Resources getResourcesForResourceName(String packageName) { 49165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda try { 49265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return mPackageManager.getResourcesForApplication(packageName); 49365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } catch (NameNotFoundException e) { 49465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda Log.d(TAG, "Could not find package: " + packageName); 49565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda return null; 49665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 49765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 49865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda } 49925594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan 50025594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan /** 50125594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan * Sets an alpha value on the view. 50225594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan */ 50325594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan public static void setAlphaOnViewBackground(View view, float alpha) { 50425594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan if (view != null) { 50525594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan // Convert alpha layer to a black background HEX color with an alpha value for better 50625594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan // performance (i.e. use setBackgroundColor() instead of setAlpha()) 50725594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan view.setBackgroundColor((int) (alpha * 255) << 24); 50825594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan } 50925594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan } 5106c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 5116c0470e21d8506fb53915df7463634fd47288343Katherine Kuan /** 5126c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Returns the top coordinate of the first item in the {@link ListView}. If the first item 5136c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * in the {@link ListView} is not visible or there are no children in the list, then return 5146c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the 5156c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * list cannot have a positive offset. 5166c0470e21d8506fb53915df7463634fd47288343Katherine Kuan */ 5176c0470e21d8506fb53915df7463634fd47288343Katherine Kuan public static int getFirstListItemOffset(ListView listView) { 5186c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView == null || listView.getChildCount() == 0 || 5196c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.getFirstVisiblePosition() != 0) { 5206c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return Integer.MIN_VALUE; 5216c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 5226c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return listView.getChildAt(0).getTop(); 5236c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 5246c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 5256c0470e21d8506fb53915df7463634fd47288343Katherine Kuan /** 5266c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * Tries to scroll the first item in the list to the given offset (this can be a no-op if the 5276c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * list is already in the correct position). 5286c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * @param listView that should be scrolled 5296c0470e21d8506fb53915df7463634fd47288343Katherine Kuan * @param offset which should be <= 0 5306c0470e21d8506fb53915df7463634fd47288343Katherine Kuan */ 5316c0470e21d8506fb53915df7463634fd47288343Katherine Kuan public static void requestToMoveToOffset(ListView listView, int offset) { 5326c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // We try to offset the list if the first item in the list is showing (which is presumed 5336c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // to have a larger height than the desired offset). If the first item in the list is not 5346c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // visible, then we simply do not scroll the list at all (since it can get complicated to 5356c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // compute how many items in the list will equal the given offset). Potentially 5366c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // some animation elsewhere will make the transition smoother for the user to compensate 5376c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // for this simplification. 5386c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView == null || listView.getChildCount() == 0 || 5396c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.getFirstVisiblePosition() != 0 || offset > 0) { 5406c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return; 5416c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 5426c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 5436c0470e21d8506fb53915df7463634fd47288343Katherine Kuan // As an optimization, check if the first item is already at the given offset. 5446c0470e21d8506fb53915df7463634fd47288343Katherine Kuan if (listView.getChildAt(0).getTop() == offset) { 5456c0470e21d8506fb53915df7463634fd47288343Katherine Kuan return; 5466c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 5476c0470e21d8506fb53915df7463634fd47288343Katherine Kuan 5486c0470e21d8506fb53915df7463634fd47288343Katherine Kuan listView.setSelectionFromTop(0, offset); 5496c0470e21d8506fb53915df7463634fd47288343Katherine Kuan } 55022cb663a251af60bc6beeb1954568c8e6a4c34e9Flavio Lerda} 551