Merge "Replaced HashMaps with LongSparseArray"
diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
index 5b51c78..992c643 100644
--- a/res/layout/contact_tile_frequent.xml
+++ b/res/layout/contact_tile_frequent.xml
@@ -24,19 +24,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <view
- android:id="@+id/image_container"
- class="com.android.contacts.list.ContactTileImageContainer"
+ <com.android.contacts.widget.LayoutSuppressingQuickContactBadge
+ android:id="@+id/contact_tile_quick"
android:layout_width="64dip"
android:layout_height="64dip"
- android:layout_alignParentRight="true">
- <QuickContactBadge
- android:id="@+id/contact_tile_quick"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop"
- android:focusable="true" />
- </view>
+ android:layout_alignParentRight="true"
+ android:scaleType="centerCrop"
+ android:focusable="true" />
<LinearLayout
android:layout_width="match_parent"
@@ -77,7 +71,7 @@
android:layout_width="match_parent"
android:layout_height="1px"
android:background="?android:attr/listDivider"
- android:layout_below="@id/image_container" />
+ android:layout_below="@id/contact_tile_quick" />
</RelativeLayout>
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index 5c7b7e2..cae5ec2 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -27,20 +27,14 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <view
- android:id="@+id/image_container"
- class="com.android.contacts.list.ContactTileImageContainer"
+ <com.android.contacts.widget.LayoutSuppressingQuickContactBadge
+ android:id="@id/contact_tile_quick"
android:layout_width="64dip"
android:layout_height="64dip"
- android:layout_alignParentLeft="true">
- <QuickContactBadge
- android:id="@id/contact_tile_quick"
- android:nextFocusRight="@id/contact_tile_frequent_phone"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop"
- android:focusable="true" />
- </view>
+ android:layout_alignParentLeft="true"
+ android:nextFocusRight="@id/contact_tile_frequent_phone"
+ android:scaleType="centerCrop"
+ android:focusable="true" />
<TextView
android:id="@+id/contact_tile_name"
@@ -49,7 +43,7 @@
android:layout_marginLeft="8dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginTop="8dip"
- android:layout_toRightOf="@id/image_container"
+ android:layout_toRightOf="@id/contact_tile_quick"
android:singleLine="true"
android:fadingEdge="horizontal"
android:fadingEdgeLength="3dip"
@@ -60,7 +54,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/contact_tile_name"
- android:layout_toRightOf="@id/image_container"
+ android:layout_toRightOf="@id/contact_tile_quick"
android:gravity="center_vertical">
<TextView
@@ -96,7 +90,7 @@
android:layout_width="match_parent"
android:layout_height="1px"
android:background="?android:attr/listDivider"
- android:layout_below="@id/image_container" />
+ android:layout_below="@id/contact_tile_quick" />
</RelativeLayout>
diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
index 91438e9..cfc74d8 100644
--- a/res/layout/contact_tile_starred.xml
+++ b/res/layout/contact_tile_starred.xml
@@ -25,16 +25,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <view
- class="com.android.contacts.list.ContactTileImageContainer"
+ <com.android.contacts.widget.LayoutSuppressingImageView
+ android:id="@+id/contact_tile_image"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageView
- android:id="@+id/contact_tile_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop" />
- </view>
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/layout/contact_tile_starred_quick_contact.xml b/res/layout/contact_tile_starred_quick_contact.xml
index 223f1b8..a396c41 100644
--- a/res/layout/contact_tile_starred_quick_contact.xml
+++ b/res/layout/contact_tile_starred_quick_contact.xml
@@ -24,16 +24,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <view
- class="com.android.contacts.list.ContactTileImageContainer"
+ <com.android.contacts.widget.LayoutSuppressingImageView
+ android:id="@+id/contact_tile_image"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageView
- android:id="@+id/contact_tile_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop" />
- </view>
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/layout/contact_tile_starred_secondary_target.xml b/res/layout/contact_tile_starred_secondary_target.xml
index 27ef3a3..ea15b86 100644
--- a/res/layout/contact_tile_starred_secondary_target.xml
+++ b/res/layout/contact_tile_starred_secondary_target.xml
@@ -24,16 +24,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <view
- class="com.android.contacts.list.ContactTileImageContainer"
+ <com.android.contacts.widget.LayoutSuppressingImageView
+ android:id="@+id/contact_tile_image"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ImageView
- android:id="@+id/contact_tile_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop" />
- </view>
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop" />
<TextView
android:id="@+id/contact_tile_name"
diff --git a/res/layout/stream_item_container.xml b/res/layout/stream_item_container.xml
index de4f87d..903f6b0 100644
--- a/res/layout/stream_item_container.xml
+++ b/res/layout/stream_item_container.xml
@@ -21,23 +21,56 @@
android:paddingLeft="@dimen/detail_update_section_side_padding"
android:paddingRight="@dimen/detail_update_section_side_padding">
+ <!-- Clickable area -->
<LinearLayout
android:id="@+id/stream_item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingLeft="@dimen/detail_update_section_item_horizontal_padding"
- android:paddingRight="@dimen/detail_update_section_item_horizontal_padding"
- android:paddingTop="@dimen/detail_update_section_item_vertical_padding"
- android:paddingBottom="@dimen/detail_update_section_item_vertical_padding"
android:background="?android:attr/selectableItemBackground"
- android:layout_gravity="center_vertical"
android:orientation="vertical"
- />
+ >
+
+ <!-- Images -->
+ <LinearLayout
+ android:id="@+id/stream_item_image_rows"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/detail_update_section_item_horizontal_padding"
+ android:paddingRight="@dimen/detail_update_section_item_horizontal_padding"
+ android:paddingTop="@dimen/detail_update_section_item_vertical_padding"
+ android:paddingBottom="@dimen/detail_update_section_between_items_vertical_padding"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical"
+ >
+ </LinearLayout>
+
+ <!-- Text -->
+ <TextView android:id="@+id/stream_item_html"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="16sp"
+ android:textColor="?android:attr/textColorPrimary" />
+ <TextView android:id="@+id/stream_item_attribution"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:ellipsize="end"
+ android:maxLines="1" />
+ <TextView android:id="@+id/stream_item_comments"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/detail_update_section_attribution_comments_padding"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="1"/>
+ </LinearLayout>
<View
android:id="@+id/horizontal_divider"
android:layout_width="match_parent"
android:layout_height="1px"
+ android:layout_marginTop="@dimen/detail_update_section_item_vertical_padding"
android:background="?android:attr/dividerHorizontal"
android:layout_gravity="bottom" />
diff --git a/res/layout/stream_item_photo.xml b/res/layout/stream_item_photo.xml
index 1fc3d0b..2649828 100644
--- a/res/layout/stream_item_photo.xml
+++ b/res/layout/stream_item_photo.xml
@@ -15,7 +15,7 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android">
- <ImageView
+ <com.android.contacts.widget.LayoutSuppressingImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
diff --git a/res/layout/stream_item_row_two_images.xml b/res/layout/stream_item_row_images.xml
similarity index 97%
rename from res/layout/stream_item_row_two_images.xml
rename to res/layout/stream_item_row_images.xml
index 7858f6f..46e1f4f 100644
--- a/res/layout/stream_item_row_two_images.xml
+++ b/res/layout/stream_item_row_images.xml
@@ -37,6 +37,7 @@
</view>
<view
+ android:id="@+id/second_image_container"
class="com.android.contacts.widget.ProportionalLayout"
android:layout_width="0dip"
android:layout_height="wrap_content"
diff --git a/res/layout/stream_item_row_one_image.xml b/res/layout/stream_item_row_one_image.xml
deleted file mode 100644
index 03dcedf..0000000
--- a/res/layout/stream_item_row_one_image.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/detail_update_section_between_items_padding"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:weightSum="2">
-
- <view
- class="com.android.contacts.widget.ProportionalLayout"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginRight="@dimen/detail_update_section_between_items_padding"
- ex:ratio="1"
- ex:direction="widthToHeight">
-
- <include
- android:id="@+id/stream_item_first_image"
- layout="@layout/stream_item_photo"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </view>
-
- </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/stream_item_row_text.xml b/res/layout/stream_item_row_text.xml
deleted file mode 100644
index 919ee52..0000000
--- a/res/layout/stream_item_row_text.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView android:id="@+id/stream_item_html"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView android:id="@+id/stream_item_attribution"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:ellipsize="end"
- android:maxLines="1" />
- <TextView android:id="@+id/stream_item_comments"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/detail_update_section_attribution_comments_padding"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:maxLines="1"/>
-
- </LinearLayout>
-</LinearLayout>
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index bb76aea..45cfe4a 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -74,6 +74,8 @@
public class ContactLoader extends Loader<ContactLoader.Result> {
private static final String TAG = "ContactLoader";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
private final Uri mRequestedUri;
private Uri mLookupUri;
private boolean mLoadGroupMetaData;
@@ -1077,6 +1079,17 @@
cursor.close();
}
+ // Pre-decode all HTMLs
+ final long start = System.currentTimeMillis();
+ for (StreamItemEntry streamItem : streamItems) {
+ streamItem.decodeHtml(getContext());
+ }
+ final long end = System.currentTimeMillis();
+ if (DEBUG) {
+ Log.d(TAG, "Decoded HTML for " + streamItems.size() + " items, took "
+ + (end - start) + " ms");
+ }
+
// Now retrieve any photo records associated with the stream items.
if (!streamItems.isEmpty()) {
if (result.isUserProfile()) {
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 08e8bfe..eabd9ec 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -354,61 +354,76 @@
/** Creates the view that represents a stream item. */
public static View createStreamItemView(LayoutInflater inflater, Context context,
- StreamItemEntry streamItem, LinearLayout parent,
- View.OnClickListener photoClickListener) {
- View container = inflater.inflate(R.layout.stream_item_container, parent, false);
- ViewGroup contentTable = (ViewGroup) container.findViewById(R.id.stream_item_content);
+ View convertView, StreamItemEntry streamItem, View.OnClickListener photoClickListener) {
- ContactPhotoManager contactPhotoManager = ContactPhotoManager.getInstance(context);
- List<StreamItemPhotoEntry> photos = streamItem.getPhotos();
+ // Try to recycle existing views.
+ final View container;
+ if (convertView != null) {
+ container = convertView;
+ } else {
+ container = inflater.inflate(R.layout.stream_item_container, null, false);
+ }
+
+ final ContactPhotoManager contactPhotoManager = ContactPhotoManager.getInstance(context);
+ final List<StreamItemPhotoEntry> photos = streamItem.getPhotos();
final int photoCount = photos.size();
- // This stream item only has text.
+ // Add the text part.
+ addStreamItemText(context, streamItem, container);
+
+ // Add images.
+ final ViewGroup imageRows = (ViewGroup) container.findViewById(R.id.stream_item_image_rows);
+
if (photoCount == 0) {
- View textOnlyContainer = inflater.inflate(R.layout.stream_item_row_text, contentTable,
- false);
- addStreamItemText(context, streamItem, textOnlyContainer);
- contentTable.addView(textOnlyContainer);
+ // This stream item only has text.
+ imageRows.setVisibility(View.GONE);
} else {
- // This stream item has text and photos. Process the photos, two at a time.
- for (int index = 0; index < photoCount; index += 2) {
- final StreamItemPhotoEntry firstPhoto = photos.get(index);
- if (index + 1 < photoCount) {
- // Put in two photos, side by side.
- final StreamItemPhotoEntry secondPhoto = photos.get(index + 1);
- View photoContainer = inflater.inflate(R.layout.stream_item_row_two_images,
- contentTable, false);
- loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer,
- R.id.stream_item_first_image, photoClickListener);
- loadPhoto(contactPhotoManager, streamItem, secondPhoto, photoContainer,
- R.id.stream_item_second_image, photoClickListener);
- contentTable.addView(photoContainer);
- } else {
- // Put in a single photo
- View photoContainer = inflater.inflate(
- R.layout.stream_item_row_one_image, contentTable, false);
- loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer,
- R.id.stream_item_first_image, photoClickListener);
- contentTable.addView(photoContainer);
+ // This stream item has text and photos.
+ imageRows.setVisibility(View.VISIBLE);
+
+ // Number of image rows needed, which is cailing(photoCount / 2)
+ final int numImageRows = (photoCount + 1) / 2;
+
+ // Actual image rows.
+ final int numOldImageRows = imageRows.getChildCount();
+
+ // Make sure we have enough stream_item_row_images.
+ if (numOldImageRows == numImageRows) {
+ // Great, we have the just enough number of rows...
+
+ } else if (numOldImageRows < numImageRows) {
+ // Need to add more image rows.
+ for (int i = numOldImageRows; i < numImageRows; i++) {
+ View imageRow = inflater.inflate(R.layout.stream_item_row_images, imageRows,
+ true);
+ }
+ } else {
+ // We have exceeding image rows. Hide them.
+ for (int i = numImageRows; i < numOldImageRows; i++) {
+ imageRows.getChildAt(i).setVisibility(View.GONE);
}
}
- // Add text, comments, and attribution if applicable
- View textContainer = inflater.inflate(R.layout.stream_item_row_text, contentTable,
- false);
- // Add extra padding between the text and the images
- int extraVerticalPadding = context.getResources().getDimensionPixelSize(
- R.dimen.detail_update_section_between_items_vertical_padding);
- textContainer.setPadding(textContainer.getPaddingLeft(),
- textContainer.getPaddingTop() + extraVerticalPadding,
- textContainer.getPaddingRight(),
- textContainer.getPaddingBottom());
- addStreamItemText(context, streamItem, textContainer);
- contentTable.addView(textContainer);
- }
+ // Put images, two by two.
+ for (int i = 0; i < photoCount; i += 2) {
+ final View imageRow = imageRows.getChildAt(i / 2);
+ // Reused image rows may not visible, so make sure they're shown.
+ imageRow.setVisibility(View.VISIBLE);
- if (parent != null) {
- parent.addView(container);
+ // Show first image.
+ loadPhoto(contactPhotoManager, streamItem, photos.get(i), imageRow,
+ R.id.stream_item_first_image, photoClickListener);
+ final View secondContainer = imageRow.findViewById(R.id.second_image_container);
+ if (i + 1 < photoCount) {
+ // Show the second image too.
+ loadPhoto(contactPhotoManager, streamItem, photos.get(i + 1), imageRow,
+ R.id.stream_item_second_image, photoClickListener);
+ secondContainer.setVisibility(View.VISIBLE);
+ } else {
+ // Hide the second image, but it still has to occupy the space.
+ secondContainer.setVisibility(View.INVISIBLE);
+ }
+ }
}
return container;
@@ -447,14 +462,12 @@
ImageGetter imageGetter = new DefaultImageGetter(context.getPackageManager());
// Stream item text
- setDataOrHideIfNone(HtmlUtils.fromHtml(context, streamItem.getText(), imageGetter, null),
- htmlView);
+ setDataOrHideIfNone(streamItem.getDecodedText(), htmlView);
// Attribution
setDataOrHideIfNone(ContactBadgeUtil.getSocialDate(streamItem, context),
attributionView);
// Comments
- setDataOrHideIfNone(HtmlUtils.fromHtml(context, streamItem.getComments(), imageGetter,
- null), commentsView);
+ setDataOrHideIfNone(streamItem.getDecodedComments(), commentsView);
return rootView;
}
@@ -516,6 +529,15 @@
}
}
+ private static Html.ImageGetter sImageGetter;
+
+ public static Html.ImageGetter getImageGetter(Context context) {
+ if (sImageGetter == null) {
+ sImageGetter = new DefaultImageGetter(context.getPackageManager());
+ }
+ return sImageGetter;
+ }
+
/** Fetcher for images from resources to be included in HTML text. */
private static class DefaultImageGetter implements Html.ImageGetter {
/** The scheme used to load resources. */
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 2d870b4..089cb07 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -104,7 +104,7 @@
manager.getAccountType(streamItem.getAccountType(), streamItem.getDataSet());
final View view = ContactDetailDisplayUtils.createStreamItemView(
- mInflater, mContext, streamItem, null,
+ mInflater, mContext, convertView, streamItem,
// Only pass the photo click listener if the account type has the photo
// view activity.
(accountType.getViewStreamItemPhotoActivity() == null) ? null : mPhotoClickListener
@@ -130,6 +130,12 @@
}
@Override
+ public int getViewTypeCount() {
+ // ITEM_VIEW_TYPE_HEADER and ITEM_VIEW_TYPE_STREAM_ITEM
+ return 2;
+ }
+
+ @Override
public int getItemViewType(int position) {
if (position == 0) {
return ITEM_VIEW_TYPE_HEADER;
diff --git a/src/com/android/contacts/list/ContactTileImageContainer.java b/src/com/android/contacts/list/ContactTileImageContainer.java
deleted file mode 100644
index e1a791b..0000000
--- a/src/com/android/contacts/list/ContactTileImageContainer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.contacts.list;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * Custom container for ImageView or ContactBadge inside {@link ContactTileView}.
- *
- * This improves the performance of favorite tabs by not passing the layout request to the parent
- * views, assuming that once measured this will not need to resize itself.
- */
-public class ContactTileImageContainer extends FrameLayout {
-
- public ContactTileImageContainer(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void requestLayout() {
- forceLayout();
- }
-}
\ No newline at end of file
diff --git a/src/com/android/contacts/util/StreamItemEntry.java b/src/com/android/contacts/util/StreamItemEntry.java
index 5959c46..6c8210f 100644
--- a/src/com/android/contacts/util/StreamItemEntry.java
+++ b/src/com/android/contacts/util/StreamItemEntry.java
@@ -16,10 +16,13 @@
package com.android.contacts.util;
+import com.android.contacts.detail.ContactDetailDisplayUtils;
import com.android.contacts.test.NeededForTesting;
+import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract.StreamItems;
+import android.text.Html;
import java.util.ArrayList;
import java.util.Collections;
@@ -36,6 +39,8 @@
private final long mId;
private final String mText;
private final String mComments;
+ private CharSequence mDecodedText;
+ private CharSequence mDecodedComments;
private final long mTimestamp;
private final String mAccountType;
private final String mAccountName;
@@ -136,6 +141,24 @@
return mPhotos;
}
+ public void decodeHtml(Context context) {
+ final Html.ImageGetter imageGetter = ContactDetailDisplayUtils.getImageGetter(context);
+ if (mText != null) {
+ mDecodedText = HtmlUtils.fromHtml(context, mText, imageGetter, null);
+ }
+ if (mComments != null) {
+ mDecodedComments = HtmlUtils.fromHtml(context, mComments, imageGetter, null);
+ }
+ }
+
+ public CharSequence getDecodedText() {
+ return mDecodedText;
+ }
+
+ public CharSequence getDecodedComments() {
+ return mDecodedComments;
+ }
+
private static String getString(Cursor cursor, String columnName) {
return cursor.getString(cursor.getColumnIndex(columnName));
}
diff --git a/src/com/android/contacts/widget/LayoutSuppressingImageView.java b/src/com/android/contacts/widget/LayoutSuppressingImageView.java
new file mode 100644
index 0000000..d80aeea
--- /dev/null
+++ b/src/com/android/contacts/widget/LayoutSuppressingImageView.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ * Custom {@link ImageView} that improves layouting performance.
+ *
+ * This improves the performance by not passing requestLayout() to its parent, taking advantage
+ * of knowing that image size won't change once set.
+ */
+public class LayoutSuppressingImageView extends ImageView {
+
+ public LayoutSuppressingImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void requestLayout() {
+ forceLayout();
+ }
+}
diff --git a/src/com/android/contacts/widget/LayoutSuppressingQuickContactBadge.java b/src/com/android/contacts/widget/LayoutSuppressingQuickContactBadge.java
new file mode 100644
index 0000000..3413e53
--- /dev/null
+++ b/src/com/android/contacts/widget/LayoutSuppressingQuickContactBadge.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.QuickContactBadge;
+
+/**
+ * Custom {@link QuickContactBadge} that improves layouting performance.
+ *
+ * This improves the performance by not passing requestLayout() to its parent, taking advantage
+ * of knowing that image size won't change once set.
+ */
+public class LayoutSuppressingQuickContactBadge extends QuickContactBadge {
+
+ public LayoutSuppressingQuickContactBadge(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void requestLayout() {
+ forceLayout();
+ }
+}
diff --git a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
index 3d383ff..fd30390 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
@@ -108,7 +108,7 @@
*/
private View addStreamItemText(StreamItemEntry streamItem) {
return ContactDetailDisplayUtils.addStreamItemText(getContext(), streamItem,
- mLayoutInflater.inflate(R.layout.stream_item_row_text, null));
+ mLayoutInflater.inflate(R.layout.stream_item_container, null));
}
private StreamItemEntryBuilder getTestBuilder() {