summaryrefslogtreecommitdiffstats
path: root/src/com/android/mail/browse
diff options
context:
space:
mode:
authorMark Wei <markwei@google.com>2013-03-21 06:04:46 -0700
committerMark Wei <markwei@google.com>2013-07-08 20:26:23 -0700
commit479505d71969e26b0785d8e0e1b81108731cf827 (patch)
tree069a592e9b3b2c8d43836e2b8ccaf47bced2fc13 /src/com/android/mail/browse
parentbb8dca879c88ad5f6de3a5ffc80b0a8e2d9e5f72 (diff)
downloadandroid_packages_apps_UnifiedEmail-479505d71969e26b0785d8e0e1b81108731cf827.tar.gz
android_packages_apps_UnifiedEmail-479505d71969e26b0785d8e0e1b81108731cf827.tar.bz2
android_packages_apps_UnifiedEmail-479505d71969e26b0785d8e0e1b81108731cf827.zip
Attachments in Conversation List: Backend changes so that the appropriate
attachments are passed to the UI. Implement PhotoManager so we can start showing images. Upon sync, we extract two image attachments from the first unread message, and add them to the conversations table. UI changes as well. Load BEST if that is available, else load SIMPLE. No vertical dividers in attachment previews. Attachment previews are above labels. Round badge appears for unread conversations when there are more images than shown. Only appears after the previews have loaded. Clicking on the attachment previews launches photoviewer. Attempt to load bigger images than necessary to prevent reloading during mark read/unread and rotate. Show animated loading icon while previews are loading. Previews load from top to bottom, from left to right. Big performance improvements: No longer decoding bitmap on UI thread. This kills most of the jank. Only load when we are not scrolling. This kills a lot of jank. Remaining jank will be delt with later: DividedImageCanvas.setDimensions() creates a huge empty bitmap on the UI thread, which causes a GC. ath will fix. Multiple images in one line now load whatever's ready first. Added tracing. Bitmap cache given more memory. Following ath's advice, decode Bitmap from InputStream rather than byte[]. Don't compress into BitmapHolder. Only use the bigger Bitmap cache. Bug: 7481049 Change-Id: Icf823f56abc9345e6d0b800a1e6d45444d8fa028
Diffstat (limited to 'src/com/android/mail/browse')
-rw-r--r--src/com/android/mail/browse/ConversationItemView.java536
-rw-r--r--src/com/android/mail/browse/ConversationItemViewCoordinates.java151
-rw-r--r--src/com/android/mail/browse/ConversationItemViewModel.java3
-rw-r--r--src/com/android/mail/browse/MessageAttachmentTile.java12
4 files changed, 570 insertions, 132 deletions
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index d1d0fbc83..8f7dcc05b 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -18,6 +18,7 @@
package com.android.mail.browse;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.ClipData;
@@ -30,6 +31,7 @@ import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
@@ -56,18 +58,30 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
import android.widget.TextView;
import com.android.mail.R;
+import com.android.mail.R.color;
+import com.android.mail.R.drawable;
+import com.android.mail.R.integer;
+import com.android.mail.R.string;
import com.android.mail.browse.ConversationItemViewModel.SenderFragment;
import com.android.mail.perf.Timer;
+import com.android.mail.photo.MailPhotoViewActivity;
+import com.android.mail.photomanager.AttachmentPreviewsManager;
+import com.android.mail.photomanager.AttachmentPreviewsManager.AttachmentPreviewsDividedImageCanvas;
+import com.android.mail.photomanager.AttachmentPreviewsManager.AttachmentPreviewsManagerCallback;
import com.android.mail.photomanager.ContactPhotoManager;
import com.android.mail.photomanager.ContactPhotoManager.ContactIdentifier;
+import com.android.mail.photomanager.AttachmentPreviewsManager.AttachmentPreviewIdentifier;
import com.android.mail.photomanager.PhotoManager.PhotoIdentifier;
import com.android.mail.providers.Address;
+import com.android.mail.providers.Attachment;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider;
+import com.android.mail.providers.UIProvider.AttachmentRendition;
import com.android.mail.providers.UIProvider.ConversationColumns;
import com.android.mail.providers.UIProvider.ConversationListIcon;
import com.android.mail.providers.UIProvider.FolderType;
@@ -77,6 +91,7 @@ import com.android.mail.ui.ConversationSelectionSet;
import com.android.mail.ui.DividedImageCanvas;
import com.android.mail.ui.DividedImageCanvas.InvalidateCallback;
import com.android.mail.ui.FolderDisplayer;
+import com.android.mail.ui.ImageCanvas;
import com.android.mail.ui.SwipeableItemView;
import com.android.mail.ui.SwipeableListView;
import com.android.mail.ui.ViewMode;
@@ -85,11 +100,14 @@ import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
+import java.util.List;
public class ConversationItemView extends View implements SwipeableItemView, ToggleableItem,
- InvalidateCallback {
+ InvalidateCallback, AttachmentPreviewsManagerCallback {
+
// Timer.
private static int sLayoutCount = 0;
private static Timer sTimer; // Create the sTimer here if you need to do
@@ -117,15 +135,19 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private static Bitmap STATE_CALENDAR_INVITE;
private static Bitmap VISIBLE_CONVERSATION_CARET;
private static Drawable RIGHT_EDGE_TABLET;
+ private static Bitmap PROGRESS_BAR;
private static String sSendersSplitToken;
private static String sElidedPaddingToken;
+ private static String sOverflowCountFormat;
// Static colors.
private static int sActivatedTextColor;
private static int sSendersTextColorRead;
private static int sSendersTextColorUnread;
private static int sDateTextColor;
+ private static int sOverflowBadgeColor;
+ private static int sOverflowTextColor;
private static int sStarTouchSlop;
private static int sSenderImageTouchSlop;
@Deprecated
@@ -133,11 +155,16 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private static int sShrinkAnimationDuration;
private static int sSlideAnimationDuration;
private static int sAnimatingBackgroundColor;
+ // todo:markwei get duration from channah
+ private static int sProgressAnimationDuration;
+ private static int sOverflowCountMax;
// Static paints.
private static TextPaint sPaint = new TextPaint();
private static TextPaint sFoldersPaint = new TextPaint();
+ private static Rect sRect = new Rect();
+
// Backgrounds for different states.
private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>();
@@ -145,9 +172,12 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private int mViewWidth = -1;
/** The view mode at which we calculated mViewWidth previously. */
private int mPreviousMode;
+
private int mDateX;
private int mPaperclipX;
private int mSendersWidth;
+ private int mOverflowX;
+ private int mOverflowY;
/** Whether we are on a tablet device or not */
private final boolean mTabletDevice;
@@ -180,8 +210,8 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private final TextView mSendersTextView;
private int mGadgetMode;
private final DividedImageCanvas mContactImagesHolder;
- private int mAttachmentPreviewMode;
- private final DividedImageCanvas mAttachmentPreviewsCanvas;
+ private static ContactPhotoManager sContactPhotoManager;
+
private static int sFoldersLeftPadding;
private static TextAppearanceSpan sSubjectTextUnreadSpan;
@@ -190,14 +220,37 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private static ForegroundColorSpan sSnippetTextReadSpan;
private static int sScrollSlop;
private static CharacterStyle sActivatedTextSpan;
- private static ContactPhotoManager sContactPhotoManager;
- private static ContactPhotoManager sAttachmentPreviewsManager;
+
+ private final AttachmentPreviewsDividedImageCanvas mAttachmentPreviewsCanvas;
+ private static AttachmentPreviewsManager sAttachmentPreviewsManager;
+ /**
+ * Animates the mAnimatedProgressFraction field to make the progress bars spin. Cancelling
+ * this animator does not remove the progress bars.
+ */
+ private final ObjectAnimator mProgressAnimator;
+ private float mAnimatedProgressFraction;
+ private boolean[] mImagesLoaded = new boolean[0];
+ private static final boolean CONVLIST_ATTACHMENT_PREVIEWS_ENABLED = true;
static {
sPaint.setAntiAlias(true);
sFoldersPaint.setAntiAlias(true);
}
+ public static void setPhotoManagersPaused(boolean shouldPause) {
+ if (sContactPhotoManager == null) {
+ return;
+ }
+
+ if (shouldPause) {
+ sContactPhotoManager.pause();
+ sAttachmentPreviewsManager.pause();
+ } else {
+ sContactPhotoManager.resume();
+ sAttachmentPreviewsManager.resume();
+ }
+ }
+
/**
* Handles displaying folders in a conversation header view.
*/
@@ -341,6 +394,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
public ConversationItemView(Context context, String account) {
super(context);
+ Utils.traceBeginSection("CIVC constructor");
setClickable(true);
setLongClickable(true);
mContext = context.getApplicationContext();
@@ -374,8 +428,9 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
BitmapFactory.decodeResource(res, R.drawable.ic_badge_invite_holo_light);
VISIBLE_CONVERSATION_CARET = BitmapFactory.decodeResource(res,
R.drawable.ic_carrot_holo);
-
RIGHT_EDGE_TABLET = res.getDrawable(R.drawable.list_edge_tablet);
+// todo:markwei get actual spinner asset from channah
+ PROGRESS_BAR = BitmapFactory.decodeResource(res, drawable.spinner_holo);
// Initialize colors.
sActivatedTextColor = res.getColor(R.color.senders_text_color_read);
@@ -391,6 +446,8 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
sSnippetTextReadSpan =
new ForegroundColorSpan(res.getColor(R.color.snippet_text_color_read));
sDateTextColor = res.getColor(R.color.date_text_color);
+ sOverflowBadgeColor = res.getColor(color.ap_overflow_badge_color);
+ sOverflowTextColor = res.getColor(color.ap_overflow_text_color);
sStarTouchSlop = res.getDimensionPixelSize(R.dimen.star_touch_slop);
sSenderImageTouchSlop = res.getDimensionPixelSize(R.dimen.sender_image_touch_slop);
sStandardScaledDimen = res.getDimensionPixelSize(R.dimen.standard_scaled_dimen);
@@ -399,11 +456,15 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
// Initialize static color.
sSendersSplitToken = res.getString(R.string.senders_split_token);
sElidedPaddingToken = res.getString(R.string.elided_padding_token);
+ sOverflowCountFormat = res.getString(string.ap_overflow_format);
sAnimatingBackgroundColor = res.getColor(R.color.animating_item_background_color);
sScrollSlop = res.getInteger(R.integer.swipeScrollSlop);
sFoldersLeftPadding = res.getDimensionPixelOffset(R.dimen.folders_left_padding);
sContactPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
- sAttachmentPreviewsManager = ContactPhotoManager.createContactPhotoManager(context);
+ sAttachmentPreviewsManager = new AttachmentPreviewsManager(context);
+ // todo:markwei get animation duration from channah
+ sProgressAnimationDuration = 1000;
+ sOverflowCountMax = res.getInteger(integer.ap_overflow_max_count);
}
mSendersTextView = new TextView(mContext);
@@ -425,29 +486,73 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mCoordinates.contactImagesY + mCoordinates.contactImagesHeight);
}
});
- mAttachmentPreviewsCanvas = new DividedImageCanvas(context, this);
+ mAttachmentPreviewsCanvas = new AttachmentPreviewsDividedImageCanvas(context,
+ new InvalidateCallback() {
+ @Override
+ public void invalidate() {
+ if (mCoordinates == null) {
+ return;
+ }
+ ConversationItemView.this.invalidate(
+ mCoordinates.attachmentPreviewsX, mCoordinates.attachmentPreviewsY,
+ mCoordinates.attachmentPreviewsX
+ + mCoordinates.attachmentPreviewsWidth,
+ mCoordinates.attachmentPreviewsY
+ + mCoordinates.attachmentPreviewsHeight);
+ }
+ });
+
+ mProgressAnimator = createProgressAnimator();
+ Utils.traceEndSection();
}
public void bind(Conversation conversation, ControllableActivity activity,
ConversationSelectionSet set, Folder folder, int checkboxOrSenderImage,
boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
+ Utils.traceBeginSection("CIVC.bind");
bind(ConversationItemViewModel.forConversation(mAccount, conversation), activity, set,
folder, checkboxOrSenderImage, swipeEnabled, priorityArrowEnabled, adapter);
+ Utils.traceEndSection();
}
private void bind(ConversationItemViewModel header, ControllableActivity activity,
ConversationSelectionSet set, Folder folder, int checkboxOrSenderImage,
boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
- // If this was previously bound to a conversation, remove any contact
- // photo manager requests.
- // TODO:MARKWEI attachment previews
if (mHeader != null) {
- final ArrayList<String> divisionIds = mContactImagesHolder.getDivisionIds();
- if (divisionIds != null) {
- mContactImagesHolder.reset();
- for (int pos = 0; pos < divisionIds.size(); pos++) {
- sContactPhotoManager.removePhoto(DividedImageCanvas.generateHash(
- mContactImagesHolder, pos, divisionIds.get(pos)));
+ // If this was previously bound to a different conversation, remove any contact photo
+ // manager requests.
+ if (header.conversation.id != mHeader.conversation.id || !header.displayableSenderNames
+ .equals(mHeader.displayableSenderNames)) {
+ ArrayList<String> divisionIds = mContactImagesHolder.getDivisionIds();
+ if (divisionIds != null) {
+ mContactImagesHolder.reset();
+ for (int pos = 0; pos < divisionIds.size(); pos++) {
+ sContactPhotoManager.removePhoto(ContactPhotoManager.generateHash(
+ mContactImagesHolder, pos, divisionIds.get(pos)));
+ }
+ }
+ }
+
+ // If this was previously bound to a different conversation,
+ // remove any attachment preview manager requests.
+ if (header.conversation.id != mHeader.conversation.id
+ || header.conversation.attachmentPreviewsCount
+ != mHeader.conversation.attachmentPreviewsCount
+ || !header.conversation.getAttachmentPreviewUris()
+ .equals(mHeader.conversation.getAttachmentPreviewUris())) {
+ ArrayList<String> divisionIds = mAttachmentPreviewsCanvas.getDivisionIds();
+ if (divisionIds != null) {
+ mAttachmentPreviewsCanvas.reset();
+ for (int pos = 0; pos < divisionIds.size(); pos++) {
+ String uri = divisionIds.get(pos);
+ for (int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
+ AttachmentPreviewIdentifier id = new AttachmentPreviewIdentifier(uri,
+ rendition, 0, 0);
+ sAttachmentPreviewsManager
+ .removePhoto(AttachmentPreviewsManager.generateHash(
+ mAttachmentPreviewsCanvas, id.getKey()));
+ }
+ }
}
}
}
@@ -459,13 +564,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mStarEnabled = folder != null && !folder.isTrash();
mSwipeEnabled = swipeEnabled;
mAdapter = adapter;
- if (mHeader.conversation.getAttachmentsCount() == 0) {
- mAttachmentPreviewMode = ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_NONE;
- } else {
- mAttachmentPreviewMode = mHeader.conversation.read ?
- ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_SHORT
- : ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_TALL;
- }
+ mImagesLoaded = new boolean[mHeader.conversation.getAttachmentPreviewUris().size()];
if (checkboxOrSenderImage == ConversationListIcon.SENDER_IMAGE) {
mGadgetMode = ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO;
@@ -495,7 +594,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mConfig = new ConversationItemViewCoordinates.Config()
.withGadget(mGadgetMode)
- .withAttachmentPreviews(mAttachmentPreviewMode);
+ .withAttachmentPreviews(getAttachmentPreviewsMode());
if (header.folderDisplayer.hasVisibleFolders()) {
mConfig.showFolders();
}
@@ -527,6 +626,9 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mConfig.showPersonalIndicator();
}
+ int overflowCount = Math.min(getOverflowCount(), sOverflowCountMax);
+ mHeader.overflowText = String.format(sOverflowCountFormat, overflowCount);
+
setContentDescription();
requestLayout();
}
@@ -552,6 +654,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ Utils.traceBeginSection("CIVC.measure");
final int wSize = MeasureSpec.getSize(widthMeasureSpec);
final int currentMode = mActivity.getViewMode().getMode();
@@ -565,11 +668,6 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
Resources res = getResources();
mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen);
- if (mHeader.standardScaledDimen != sStandardScaledDimen) {
- // Large Text has been toggle on/off. Update the static dimens.
- sStandardScaledDimen = mHeader.standardScaledDimen;
- ConversationItemViewCoordinates.refreshConversationDimens(mContext);
- }
mCoordinates = ConversationItemViewCoordinates.forConfig(mContext, mConfig,
mAdapter.getCoordinatesCache());
@@ -577,6 +675,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
final int h = (mAnimatedHeightFraction != 1.0f) ?
Math.round(mAnimatedHeightFraction * mCoordinates.height) : mCoordinates.height;
setMeasuredDimension(mConfig.getWidth(), h);
+ Utils.traceEndSection();
}
@Override
@@ -615,6 +714,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
@Override
public void setBackgroundResource(int resourceId) {
+ Utils.traceBeginSection("set background resource");
Drawable drawable = mBackgrounds.get(resourceId);
if (drawable == null) {
drawable = getResources().getDrawable(resourceId);
@@ -623,6 +723,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
if (getBackground() != drawable) {
super.setBackgroundDrawable(drawable);
}
+ Utils.traceEndSection();
}
private void calculateTextsAndBitmaps() {
@@ -677,7 +778,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
}
- if (mAttachmentPreviewMode != ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_NONE) {
+ if (isAttachmentPreviewsEnabled()) {
loadAttachmentPreviews();
}
@@ -702,6 +803,30 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
}
+ private boolean isAttachmentPreviewsEnabled() {
+ return CONVLIST_ATTACHMENT_PREVIEWS_ENABLED
+ && mHeader.conversation.attachmentPreviewsCount != 0;
+ }
+
+ private boolean getOverflowCountVisible() {
+ return isAttachmentPreviewsEnabled() && getOverflowCount() > 0;
+ }
+
+ private int getOverflowCount() {
+ return mHeader.conversation.attachmentPreviewsCount - mHeader.conversation
+ .getAttachmentPreviewUris().size();
+ }
+
+ private int getAttachmentPreviewsMode() {
+ if (isAttachmentPreviewsEnabled()) {
+ return mHeader.conversation.read
+ ? ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_READ
+ : ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_UNREAD;
+ } else {
+ return ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_NONE;
+ }
+ }
+
// FIXME(ath): maybe move this to bind(). the only dependency on layout is on tile W/H, which
// is immutable.
private void loadSenderImages() {
@@ -715,10 +840,16 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mCoordinates.getMode());
return;
}
+
+ int size = mHeader.displayableSenderEmails.size();
+ final List<Object> keys = Lists.newArrayListWithCapacity(size);
+ for (int i = 0; i < DividedImageCanvas.MAX_DIVISIONS && i < size; i++) {
+ keys.add(mHeader.displayableSenderEmails.get(i));
+ }
+
mContactImagesHolder.setDimensions(mCoordinates.contactImagesWidth,
mCoordinates.contactImagesHeight);
- mContactImagesHolder.setDivisionIds(mHeader.displayableSenderEmails);
- int size = mHeader.displayableSenderEmails.size();
+ mContactImagesHolder.setDivisionIds(keys);
String emailAddress;
for (int i = 0; i < DividedImageCanvas.MAX_DIVISIONS && i < size; i++) {
emailAddress = mHeader.displayableSenderEmails.get(i);
@@ -730,29 +861,122 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
private void loadAttachmentPreviews() {
- if (mAttachmentPreviewMode != ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_NONE) {
- final int attachmentPreviewsHeight = ConversationItemViewCoordinates
- .getAttachmentPreviewsHeight(mContext, mAttachmentPreviewMode);
- if (mCoordinates.attachmentPreviewsWidth <= 0 || attachmentPreviewsHeight <= 0) {
- LogUtils.w(LOG_TAG,
- "Attachment preview width(%d) or height(%d) is 0 for mode: (%d,%d).",
- mCoordinates.attachmentPreviewsWidth, attachmentPreviewsHeight,
- mCoordinates.getMode(), mAttachmentPreviewMode);
- return;
+ if (!isAttachmentPreviewsEnabled()) {
+ return;
+ }
+ if (mCoordinates.attachmentPreviewsWidth <= 0
+ || mCoordinates.attachmentPreviewsHeight <= 0) {
+ LogUtils.w(LOG_TAG,
+ "Attachment preview width(%d) or height(%d) is 0 for mode: (%d,%d).",
+ mCoordinates.attachmentPreviewsWidth, mCoordinates.attachmentPreviewsHeight,
+ mCoordinates.getMode(), getAttachmentPreviewsMode());
+ return;
+ }
+ Utils.traceBeginSection("attachment previews");
+
+ Utils.traceBeginSection("Setup load attachment previews");
+
+ LogUtils.d(LOG_TAG,
+ "loadAttachmentPreviews: ###############################################");
+ LogUtils.d(LOG_TAG,
+ "loadAttachmentPreviews: Loading attachment previews for conversation %s",
+ mHeader.conversation);
+
+ // Get list of attachments and states from conversation
+ final ArrayList<String> attachmentUris = mHeader.conversation.getAttachmentPreviewUris();
+ final int previewStates = mHeader.conversation.attachmentPreviewStates;
+ final int displayCount = Math.min(attachmentUris.size(), DividedImageCanvas.MAX_DIVISIONS);
+ Utils.traceEndSection();
+
+ final List<AttachmentPreviewIdentifier> ids = Lists.newArrayListWithCapacity(displayCount);
+ final List<Object> keys = Lists.newArrayListWithCapacity(displayCount);
+ // First pass: Create and set the rendition on each load request
+ for (int i = 0; i < displayCount; i++) {
+ Utils.traceBeginSection("finding rendition of attachment preview");
+ final String uri = attachmentUris.get(i);
+
+ // Find the rendition to load based on availability.
+ LogUtils.d(LOG_TAG, "loadAttachmentPreviews: state [BEST, SIMPLE] is [%s, %s] for %s ",
+ Attachment.getPreviewState(previewStates, i, AttachmentRendition.BEST),
+ Attachment.getPreviewState(previewStates, i, AttachmentRendition.SIMPLE),
+ uri);
+ int bestAvailableRendition = -1;
+ // BEST first, else use less preferred renditions
+ for (int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
+ if (Attachment.getPreviewState(previewStates, i, rendition)) {
+ bestAvailableRendition = rendition;
+ break;
+ }
}
- mAttachmentPreviewsCanvas.setDimensions(mCoordinates.attachmentPreviewsWidth,
- attachmentPreviewsHeight);
- ArrayList<String> attachments = mHeader.conversation.getAttachments();
- mAttachmentPreviewsCanvas.setDivisionIds(attachments);
- int size = attachments.size();
- for (int i = 0; i < DividedImageCanvas.MAX_DIVISIONS && i < size; i++) {
- String attachment = attachments.get(i);
- PhotoIdentifier photoIdentifier = new ContactIdentifier(
- attachment, attachment, i);
- sAttachmentPreviewsManager.loadThumbnail(
- photoIdentifier, mAttachmentPreviewsCanvas);
+
+ final AttachmentPreviewIdentifier photoIdentifier = new AttachmentPreviewIdentifier(uri,
+ bestAvailableRendition, mHeader.conversation.id, i);
+ ids.add(photoIdentifier);
+ keys.add(photoIdentifier.getKey());
+ Utils.traceEndSection();
+ }
+
+ Utils.traceBeginSection("preparing divided image canvas");
+ // Prepare the canvas.
+ mAttachmentPreviewsCanvas.setDimensions(mCoordinates.attachmentPreviewsWidth,
+ mCoordinates.attachmentPreviewsHeight);
+ mAttachmentPreviewsCanvas.setDivisionIds(keys);
+ Utils.traceEndSection();
+
+ // Second pass: Find the dimensions to load and start the load request
+ final ImageCanvas.Dimensions canvasDimens = new ImageCanvas.Dimensions();
+ for (int i = 0; i < displayCount; i++) {
+ final PhotoIdentifier photoIdentifier = ids.get(i);
+ final Object key = keys.get(i);
+ mAttachmentPreviewsCanvas.getDesiredDimensions(key, canvasDimens);
+ if (i < mImagesLoaded.length) {
+ // We want to show default progress image
+ mImagesLoaded[i] = false;
+ if (!mProgressAnimator.isStarted()) {
+ LogUtils.d(LOG_TAG, "progress animator: >> started");
+ mProgressAnimator.setCurrentPlayTime(
+ (long) (sProgressAnimationDuration * mAnimatedProgressFraction));
+ mProgressAnimator.start();
+ }
}
+ LogUtils.d(LOG_TAG, "loadAttachmentPreviews: start loading %s", photoIdentifier);
+ sAttachmentPreviewsManager
+ .loadThumbnail(photoIdentifier, mAttachmentPreviewsCanvas, canvasDimens, this);
}
+ Utils.traceEndSection();
+ }
+
+ @Override
+ public void onImageDrawn(Object key, boolean success) {
+ Utils.traceBeginSection("on image drawn");
+ String uri = AttachmentPreviewsManager.transformKeyToUri(key);
+ int index = mHeader.conversation.getAttachmentPreviewUris().indexOf(uri);
+
+ if (index < 0 || index >= mImagesLoaded.length) {
+ Utils.traceEndSection();
+ return;
+ }
+
+ LogUtils.d(LOG_TAG,
+ "loadAttachmentPreviews: <= onImageDrawn callback [%b] on index %d for %s", success,
+ index, key);
+ // We want to hide the spinning progress bar when we draw something.
+ mImagesLoaded[index] = success;
+
+ if (mProgressAnimator.isStarted() && areAllImagesLoaded()) {
+ LogUtils.d(LOG_TAG, "progress animator: << stopped");
+ mProgressAnimator.cancel();
+ }
+ Utils.traceEndSection();
+ }
+
+ private boolean areAllImagesLoaded() {
+ for (int i = 0; i < mImagesLoaded.length; i++) {
+ if (!mImagesLoaded[i]) {
+ return false;
+ }
+ }
+ return true;
}
private static int makeExactSpecForSize(int size) {
@@ -902,6 +1126,19 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mSendersWidth = 0;
}
+ String overflowText = mHeader.overflowText != null ? mHeader.overflowText : "";
+ sPaint.setTextSize(mCoordinates.overflowFontSize);
+ sPaint.setTypeface(mCoordinates.overflowTypeface);
+
+ sPaint.getTextBounds(overflowText, 0, overflowText.length(), sRect);
+
+ final int overflowWidth = (int) sPaint.measureText(overflowText);
+ final int overflowHeight = sRect.height();
+ mOverflowX = mCoordinates.overflowXEnd - mCoordinates.overflowDiameter / 2
+ - overflowWidth / 2;
+ mOverflowY = mCoordinates.overflowYEnd - mCoordinates.overflowDiameter / 2
+ + overflowHeight / 2;
+
pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
}
@@ -1091,12 +1328,14 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
@Override
protected void onDraw(Canvas canvas) {
Utils.traceBeginSection("CIVC.draw");
+
// Contact photo
if (mGadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO) {
canvas.save();
drawContactImages(canvas);
canvas.restore();
}
+
// Senders.
boolean isUnread = mHeader.unread;
// Old style senders; apply text colors/ sizes/ styling.
@@ -1174,10 +1413,36 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
// Attachment previews
- if (mAttachmentPreviewMode != ConversationItemViewCoordinates.ATTACHMENT_PREVIEW_NONE) {
+ if (isAttachmentPreviewsEnabled()) {
canvas.save();
drawAttachmentPreviews(canvas);
canvas.restore();
+
+ // Overflow badge and count
+ if (getOverflowCountVisible() && areAllImagesLoaded()) {
+ float radius = mCoordinates.overflowDiameter / 2;
+ // todo:markwei get color of overflow badge from channah
+ sPaint.setColor(sOverflowBadgeColor);
+ canvas.drawCircle(mCoordinates.overflowXEnd - radius,
+ mCoordinates.overflowYEnd - radius, radius, sPaint);
+
+ sPaint.setTextSize(mCoordinates.overflowFontSize);
+ sPaint.setTypeface(mCoordinates.overflowTypeface);
+ sPaint.setColor(sOverflowTextColor);
+ drawText(canvas, mHeader.overflowText, mOverflowX, mOverflowY, sPaint);
+ }
+
+ // Progress bar
+ if (mProgressAnimator.isRunning()) {
+ final int count = mImagesLoaded.length;
+ for (int i = 0; i < count; i++) {
+ if (!mImagesLoaded[i]) {
+ canvas.save();
+ drawProgressBar(canvas, i, count);
+ canvas.restore();
+ }
+ }
+ }
}
// right-side edge effect when in tablet conversation mode and the list is not collapsed
@@ -1217,6 +1482,50 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mSendersTextView.draw(canvas);
}
+ /**
+ * Draws the specified progress bar on the canvas.
+ * @param canvas The canvas to draw on.
+ * @param index If drawing multiple progress bars, this determines which one we are drawing.
+ * @param total Whether we are drawing multiple progress bars.
+ */
+ private void drawProgressBar(Canvas canvas, int index, int total) {
+ int progressBarX = getProgressBarX(index, total);
+ if (progressBarX == -1) {
+ return;
+ }
+
+ // We want to rotate counter-clockwise, because that's the direction the asset faces
+ canvas.rotate(360 - mAnimatedProgressFraction * 360,
+ progressBarX + mCoordinates.progressBarWidth / 2,
+ mCoordinates.progressBarY + mCoordinates.progressBarHeight / 2);
+
+ canvas.drawBitmap(PROGRESS_BAR, progressBarX, mCoordinates.progressBarY, null);
+ }
+
+ /**
+ * @see com.android.mail.browse.ConversationItemView#drawProgressBar
+ */
+ private void invalidateProgressBar(int index, int total) {
+ int progressBarX = getProgressBarX(index, total);
+ if (progressBarX == -1) {
+ return;
+ }
+
+ invalidate(progressBarX, mCoordinates.progressBarY,
+ progressBarX + mCoordinates.progressBarWidth,
+ mCoordinates.progressBarY + mCoordinates.progressBarHeight);
+ }
+
+ private int getProgressBarX(int index, int total) {
+ if (mCoordinates == null) {
+ return -1;
+ }
+ int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ int sectionOffset = index * sectionWidth;
+ return mCoordinates.attachmentPreviewsX + sectionOffset + sectionWidth / 2
+ - mCoordinates.progressBarWidth / 2;
+ }
+
private Bitmap getStarBitmap() {
return mHeader.conversation.starred ? STAR_ON : STAR_OFF;
}
@@ -1297,16 +1606,49 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
}
- private boolean isTouchInContactPhoto(float x) {
+ public void viewAttachmentPreview(int index) {
+ Uri imageListUri = mHeader.conversation.attachmentPreviewsListUri;
+ LogUtils.d(LOG_TAG,
+ "ConversationItemView: tapped on attachment preview %d, "
+ + "opening photoviewer for image list uri %s",
+ index, imageListUri);
+ MailPhotoViewActivity
+ .startMailPhotoViewActivity(mActivity.getActivityContext(), imageListUri, index);
+ }
+
+ private boolean isTouchInContactPhoto(float x, float y) {
// Everything before the right edge of contact photo
- return (mHeader.gadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO
- && x < (mCoordinates.contactImagesX + mCoordinates.contactImagesWidth
- + sSenderImageTouchSlop));
+ return mHeader.gadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO
+ && x < mCoordinates.contactImagesX + mCoordinates.contactImagesWidth
+ + sSenderImageTouchSlop
+ && (!isAttachmentPreviewsEnabled() || y < mCoordinates.attachmentPreviewsY);
}
private boolean isTouchInStar(float x, float y) {
// Everything after the star and include a touch slop.
- return mStarEnabled && x > mCoordinates.starX - sStarTouchSlop;
+ return mStarEnabled
+ && x > mCoordinates.starX - sStarTouchSlop
+ && (!isAttachmentPreviewsEnabled() || y < mCoordinates.attachmentPreviewsY);
+ }
+
+ /**
+ * If the touch is in the attachment previews, return the index of the attachment under that
+ * point (for multiple previews). Return -1 if the touch is outside of the previews.
+ */
+ private int getAttachmentPreviewsIndexForTouch(float x, float y) {
+ if (!isAttachmentPreviewsEnabled()) {
+ return -1;
+ }
+ if (y > mCoordinates.attachmentPreviewsY
+ && y < mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight
+ && x > mCoordinates.attachmentPreviewsX
+ && x < mCoordinates.attachmentPreviewsX + mCoordinates.attachmentPreviewsWidth) {
+ int eachWidth = mCoordinates.attachmentPreviewsWidth / mHeader.conversation
+ .getAttachmentPreviewUris().size();
+ int offset = (int) (x - mCoordinates.attachmentPreviewsX);
+ return offset / eachWidth;
+ }
+ return -1;
}
@Override
@@ -1323,6 +1665,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
private boolean onTouchEventNoSwipe(MotionEvent event) {
+ Utils.traceBeginSection("on touch event no swipe");
boolean handled = false;
int x = (int) event.getX();
@@ -1331,7 +1674,8 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mLastTouchY = y;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- if (isTouchInContactPhoto(x) || isTouchInStar(x, y)) {
+ if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)
+ || getAttachmentPreviewsIndexForTouch(x, y) > -1) {
mDownEvent = true;
handled = true;
}
@@ -1343,12 +1687,16 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
case MotionEvent.ACTION_UP:
if (mDownEvent) {
- if (isTouchInContactPhoto(x)) {
+ int index;
+ if (isTouchInContactPhoto(x, y)) {
// Touch on the check mark
toggleSelectedState();
} else if (isTouchInStar(x, y)) {
// Touch on the star
toggleStar();
+ } else if ((index = getAttachmentPreviewsIndexForTouch(x, y)) > -1) {
+ // Touch on an attachment preview
+ viewAttachmentPreview(index);
}
handled = true;
}
@@ -1359,6 +1707,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
handled = super.onTouchEvent(event);
}
+ Utils.traceEndSection();
return handled;
}
@@ -1367,31 +1716,45 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
+ Utils.traceBeginSection("on touch event");
int x = (int) event.getX();
int y = (int) event.getY();
mLastTouchX = x;
mLastTouchY = y;
if (!mSwipeEnabled) {
+ Utils.traceEndSection();
return onTouchEventNoSwipe(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- if (isTouchInContactPhoto(x) || isTouchInStar(x, y)) {
+ if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)
+ || getAttachmentPreviewsIndexForTouch(x, y) > -1) {
mDownEvent = true;
+ Utils.traceEndSection();
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mDownEvent) {
- if (isTouchInContactPhoto(x)) {
+ int index;
+ if (isTouchInContactPhoto(x, y)) {
// Touch on the check mark
+ Utils.traceEndSection();
mDownEvent = false;
toggleSelectedState();
+ Utils.traceEndSection();
return true;
} else if (isTouchInStar(x, y)) {
// Touch on the star
mDownEvent = false;
toggleStar();
+ Utils.traceEndSection();
+ return true;
+ } else if ((index = getAttachmentPreviewsIndexForTouch(x, y)) > -1) {
+ // Touch on an attachment preview
+ mDownEvent = false;
+ viewAttachmentPreview(index);
+ Utils.traceEndSection();
return true;
}
}
@@ -1400,8 +1763,10 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
// Let View try to handle it as well.
boolean handled = super.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ Utils.traceEndSection();
return true;
}
+ Utils.traceEndSection();
return handled;
}
@@ -1430,9 +1795,16 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
* can be reused.
*/
public void reset() {
+ Utils.traceBeginSection("reset");
setAlpha(1f);
setTranslationX(0f);
mAnimatedHeightFraction = 1.0f;
+ LogUtils.d(LOG_TAG, "progress animator: cancelling after %dms", sProgressAnimationDuration);
+ if (mProgressAnimator.isStarted()) {
+ LogUtils.d(LOG_TAG, "progress animator: << stopped");
+ mProgressAnimator.cancel();
+ }
+ Utils.traceEndSection();
}
@SuppressWarnings("deprecation")
@@ -1525,6 +1897,44 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
requestLayout();
}
+ private ObjectAnimator createProgressAnimator() {
+ ObjectAnimator animator = ObjectAnimator.ofFloat(this, "animatedProgressFraction", 0f, 1.0f)
+ .setDuration(sProgressAnimationDuration);
+ animator.setInterpolator(new LinearInterpolator());
+ animator.setRepeatCount(ObjectAnimator.INFINITE);
+ animator.setRepeatMode(ObjectAnimator.RESTART);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ invalidateAll();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ invalidateAll();
+ }
+
+ private void invalidateAll() {
+ int count = mHeader.conversation.getAttachmentPreviewUris().size();
+ for (int i = 0; i < count; i++) {
+ invalidateProgressBar(i, count);
+ }
+ }
+ });
+ return animator;
+ }
+
+ // Used by animator
+ public void setAnimatedProgressFraction(float fraction) {
+ mAnimatedProgressFraction = fraction;
+ final int count = mImagesLoaded.length;
+ for (int i = 0; i < count; i++) {
+ if (!mImagesLoaded[i]) {
+ invalidateProgressBar(i, count);
+ }
+ }
+ }
+
@Override
public SwipeableView getSwipeableView() {
return SwipeableView.from(this);
diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
index 85b016651..34b5596b3 100644
--- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java
+++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
@@ -28,9 +28,12 @@ import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
+import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.mail.R;
+import com.android.mail.R.dimen;
+import com.android.mail.R.id;
import com.android.mail.ui.ViewMode;
import com.android.mail.utils.Utils;
import com.google.common.base.Objects;
@@ -56,10 +59,9 @@ public class ConversationItemViewCoordinates {
static final int GADGET_CHECKBOX = 2;
// Attachment previews modes
- static final int ATTACHMENT_PREVIEW_MODE_COUNT = 3;
static final int ATTACHMENT_PREVIEW_NONE = 0;
- static final int ATTACHMENT_PREVIEW_TALL = 1;
- static final int ATTACHMENT_PREVIEW_SHORT = 2;
+ static final int ATTACHMENT_PREVIEW_UNREAD = 1;
+ static final int ATTACHMENT_PREVIEW_READ = 2;
// For combined views
private static int COLOR_BLOCK_WIDTH = -1;
@@ -167,13 +169,6 @@ public class ConversationItemViewCoordinates {
final int height;
- // Attachments view
- static int sAttachmentPreviewsHeights[];
- static int sAttachmentPreviewsMarginTops[];
- final int attachmentPreviewsX;
- final int attachmentPreviewsY;
- final int attachmentPreviewsWidth;
-
// Checkmark.
final int checkmarkX;
final int checkmarkY;
@@ -181,6 +176,7 @@ public class ConversationItemViewCoordinates {
// Star.
final int starX;
final int starY;
+ final int starWidth;
// Senders.
final int sendersX;
@@ -241,6 +237,24 @@ public class ConversationItemViewCoordinates {
final int contactImagesX;
final int contactImagesY;
+ // Attachment previews
+ final int attachmentPreviewsX;
+ final int attachmentPreviewsY;
+ final int attachmentPreviewsWidth;
+ final int attachmentPreviewsHeight;
+
+ // Attachment previews overflow badge and count
+ final int overflowXEnd;
+ final int overflowYEnd;
+ final int overflowDiameter;
+ final float overflowFontSize;
+ final Typeface overflowTypeface;
+
+ // Attachment previews progress bar
+ final int progressBarY;
+ final int progressBarWidth;
+ final int progressBarHeight;
+
/**
* The smallest item width for which we use the "wide" layout.
*/
@@ -255,6 +269,7 @@ public class ConversationItemViewCoordinates {
private final int mFolderMinimumWidth;
private ConversationItemViewCoordinates(Context context, Config config) {
+ Utils.traceBeginSection("CIV coordinates constructor");
final Resources res = context.getResources();
mFolderCellWidth = res.getDimensionPixelSize(R.dimen.folder_cell_width);
mMinListWidthForWide = res.getDimensionPixelSize(R.dimen.list_min_width_is_wide);
@@ -276,22 +291,27 @@ public class ConversationItemViewCoordinates {
}
final ViewGroup view = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);
- final TextView folders = (TextView) view.findViewById(R.id.folders);
- folders.setVisibility(config.areFoldersVisible() ? View.VISIBLE : View.GONE);
-
// Show/hide optional views before measure/layout call
+
View attachmentPreviews = null;
if (config.getAttachmentPreviewMode() != ATTACHMENT_PREVIEW_NONE) {
attachmentPreviews = view.findViewById(R.id.attachment_previews);
- if (attachmentPreviews != null) {
- LayoutParams params = attachmentPreviews.getLayoutParams();
- attachmentPreviews.setVisibility(View.VISIBLE);
- params.height = getAttachmentPreviewsHeight(
- context, config.getAttachmentPreviewMode());
- attachmentPreviews.setLayoutParams(params);
- }
+ LayoutParams params = attachmentPreviews.getLayoutParams();
+ attachmentPreviews.setVisibility(View.VISIBLE);
+ params.height = getAttachmentPreviewsHeight(context, config.getAttachmentPreviewMode());
+ attachmentPreviews.setLayoutParams(params);
}
+ final TextView folders = (TextView) view.findViewById(R.id.folders);
+ folders.setVisibility(config.areFoldersVisible() ? View.VISIBLE : View.GONE);
+
+ // Add margin between attachment previews and folders
+ View attachmentPreviewsBottomMargin = view
+ .findViewById(R.id.attachment_previews_bottom_margin);
+ attachmentPreviewsBottomMargin.setVisibility(
+ attachmentPreviews != null && config.areFoldersVisible() ? View.VISIBLE
+ : View.GONE);
+
View contactImagesView = view.findViewById(R.id.contact_image);
View checkmark = view.findViewById(R.id.checkmark);
@@ -351,6 +371,7 @@ public class ConversationItemViewCoordinates {
final View star = view.findViewById(R.id.star);
starX = getX(star);
starY = getY(star);
+ starWidth = star.getWidth();
final TextView senders = (TextView) view.findViewById(R.id.senders);
final int sendersTopAdjust = getLatinTopAdjustment(senders);
@@ -440,16 +461,50 @@ public class ConversationItemViewCoordinates {
paperclipPaddingLeft = paperclip.getPaddingLeft();
if (attachmentPreviews != null) {
- attachmentPreviewsX = getX(attachmentPreviews);
- attachmentPreviewsY = getY(attachmentPreviews);
- attachmentPreviewsWidth = attachmentPreviews.getWidth();
+ attachmentPreviewsX = getAttachmentPreviewsX(attachmentPreviews,
+ config.mAttachmentPreviewMode);
+ attachmentPreviewsY = getY(attachmentPreviews) + sendersTopAdjust;
+ final int attachmentPreviewsXEnd;
+ if (isWide()) {
+ attachmentPreviewsXEnd = subjectX + subjectWidth;
+ } else {
+ attachmentPreviewsXEnd = starX + starWidth;
+ }
+
+ attachmentPreviewsWidth = attachmentPreviewsXEnd - attachmentPreviewsX;
+ attachmentPreviewsHeight = attachmentPreviews.getHeight();
+
+ // We only care about the right and bottom of the overflow count
+ final TextView overflow = (TextView) view.findViewById(id.ap_overflow);
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) overflow.getLayoutParams();
+ overflowXEnd = attachmentPreviewsX + attachmentPreviewsWidth - params.rightMargin;
+ overflowYEnd = attachmentPreviewsY + attachmentPreviewsHeight - params.bottomMargin;
+ overflowDiameter = overflow.getWidth();
+ overflowFontSize = overflow.getTextSize();
+ overflowTypeface = overflow.getTypeface();
+
+ final View progressBar = view.findViewById(id.ap_progress_bar);
+ progressBarWidth = progressBar.getWidth();
+ progressBarHeight = progressBar.getHeight();
+ progressBarY = attachmentPreviewsY + attachmentPreviewsHeight / 2
+ - progressBarHeight / 2;
} else {
attachmentPreviewsX = 0;
attachmentPreviewsY = 0;
attachmentPreviewsWidth = 0;
+ attachmentPreviewsHeight = 0;
+ overflowXEnd = 0;
+ overflowYEnd = 0;
+ overflowDiameter = 0;
+ overflowFontSize = 0;
+ overflowTypeface = null;
+ progressBarY = 0;
+ progressBarWidth = 0;
+ progressBarHeight = 0;
}
height = view.getHeight() + (isWide() ? 0 : sendersTopAdjust);
+ Utils.traceEndSection();
}
public int getMode() {
@@ -490,48 +545,24 @@ public class ConversationItemViewCoordinates {
}
}
- /**
- * Returns a value array multiplied by the specified density.
- */
- public static int[] getDensityDependentArray(int[] values, float density) {
- int result[] = new int[values.length];
- for (int i = 0; i < values.length; ++i) {
- result[i] = (int) (values[i] * density);
+ private int getAttachmentPreviewsX(View attachmentPreviews, int attachmentPreviewMode) {
+ if (isWide() || attachmentPreviewMode == ATTACHMENT_PREVIEW_READ) {
+ return subjectX;
}
- return result;
+ return getX(attachmentPreviews);
}
- /**
- * Refreshes the conversation heights array.
- */
- @Deprecated
- // TODO: heights are now dynamic and should be members of this class. the fixed attachment
- // heights can still be stored in a dimensional array, but should only be used as input into
- // forConfig's measure/layout
- public static void refreshConversationDimens(Context context) {
+ private int getAttachmentPreviewsHeight(Context context, int attachmentPreviewMode) {
Resources res = context.getResources();
-
- // Attachment previews height
- sAttachmentPreviewsHeights = new int[ATTACHMENT_PREVIEW_MODE_COUNT];
- sAttachmentPreviewsHeights[ATTACHMENT_PREVIEW_TALL] = 0;
- sAttachmentPreviewsHeights[ATTACHMENT_PREVIEW_TALL] = (int) res.getDimension(
- R.dimen.attachment_preview_height_tall);
- sAttachmentPreviewsHeights[ATTACHMENT_PREVIEW_SHORT] = (int) res.getDimension(
- R.dimen.attachment_preview_height_short);
-
- // Attachment previews margin top
- sAttachmentPreviewsMarginTops = new int[MODE_COUNT];
- sAttachmentPreviewsMarginTops[NORMAL_MODE] = (int) res.getDimension(
- R.dimen.attachment_preview_margin_top);
- sAttachmentPreviewsMarginTops[WIDE_MODE] = (int) res.getDimension(
- R.dimen.attachment_preview_margin_top_wide);
- }
-
- public static int getAttachmentPreviewsHeight(Context context, int attachmentPreviewMode) {
- if (sAttachmentPreviewsHeights == null) {
- refreshConversationDimens(context);
+ switch (attachmentPreviewMode) {
+ case ATTACHMENT_PREVIEW_UNREAD:
+ return (int) (isWide() ? res.getDimension(dimen.attachment_preview_height_tall_wide)
+ : res.getDimension(dimen.attachment_preview_height_tall));
+ case ATTACHMENT_PREVIEW_READ:
+ return (int) res.getDimension(dimen.attachment_preview_height_short);
+ default:
+ return 0;
}
- return sAttachmentPreviewsHeights[attachmentPreviewMode];
}
/**
diff --git a/src/com/android/mail/browse/ConversationItemViewModel.java b/src/com/android/mail/browse/ConversationItemViewModel.java
index 303ec5902..ad6c0d857 100644
--- a/src/com/android/mail/browse/ConversationItemViewModel.java
+++ b/src/com/android/mail/browse/ConversationItemViewModel.java
@@ -86,6 +86,9 @@ public class ConversationItemViewModel {
boolean hasDraftMessage;
+ // Attachment Previews overflow
+ String overflowText;
+
// View Width
public int viewWidth;
diff --git a/src/com/android/mail/browse/MessageAttachmentTile.java b/src/com/android/mail/browse/MessageAttachmentTile.java
index ece218353..693df5b29 100644
--- a/src/com/android/mail/browse/MessageAttachmentTile.java
+++ b/src/com/android/mail/browse/MessageAttachmentTile.java
@@ -154,14 +154,8 @@ public class MessageAttachmentTile extends AttachmentTile implements OnClickList
@Override
public void viewAttachment() {
if (ImageUtils.isImageMimeType(Utils.normalizeMimeType(mAttachment.getContentType()))) {
- final PhotoViewIntentBuilder builder =
- Intents.newPhotoViewIntentBuilder(getContext(), MailPhotoViewActivity.class);
- builder
- .setPhotosUri(mAttachmentsListUri.toString())
- .setProjection(UIProvider.ATTACHMENT_PROJECTION)
- .setPhotoIndex(mPhotoIndex);
-
- getContext().startActivity(builder.build());
+ MailPhotoViewActivity
+ .startMailPhotoViewActivity(getContext(), mAttachmentsListUri, mPhotoIndex);
return;
}
@@ -213,7 +207,7 @@ public class MessageAttachmentTile extends AttachmentTile implements OnClickList
/**
* Given two child views, figure out whose index is closest to the specified
- * index. (generated by markwei)
+ * index.
*/
public static class ViewIndexDistanceComparator implements Comparator<View>{
final private int mIndex;