summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proguard.flags2
-rw-r--r--res/values/colors.xml1
-rw-r--r--res/values/constants.xml2
-rw-r--r--src/com/android/mail/browse/ConversationItemView.java396
-rw-r--r--src/com/android/mail/browse/ConversationItemViewCoordinates.java27
-rw-r--r--src/com/android/mail/photomanager/PhotoManager.java22
-rw-r--r--src/com/android/mail/ui/SwipeableListView.java2
7 files changed, 302 insertions, 150 deletions
diff --git a/proguard.flags b/proguard.flags
index 5d904420e..ea8cf79f2 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -61,6 +61,8 @@
-keepclasseswithmembers class com.android.mail.browse.ConversationItemView {
*** setAnimatedHeightFraction(...);
*** setAnimatedProgressFraction(...);
+ *** setAnimatedFadeFraction0(...);
+ *** setAnimatedFadeFraction1(...);
}
-keepclasseswithmembers class com.android.mail.ui.MailActivity {
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 21197aa2d..c1bb18056 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -32,6 +32,7 @@
<color name="date_text_color">@color/dark_gray_text_color</color>
<color name="message_info_text_color">@color/gray_text_color</color>
<color name="subject_text_color">#333333</color>
+ <color name="ap_background_color">#fff1f1f2</color>
<color name="ap_overflow_badge_color">#eeeeeeee</color>
<color name="ap_overflow_text_color">#ff4f4c4c</color>
<!-- a 'checked' item is in the conversation selection set. also the 'pressed' color. -->
diff --git a/res/values/constants.xml b/res/values/constants.xml
index 4cf939934..7574ffa92 100644
--- a/res/values/constants.xml
+++ b/res/values/constants.xml
@@ -117,6 +117,8 @@
<!-- Duration of progress bar animation for attachment previews -->
<integer name="ap_progress_animation_duration">4000</integer>
+ <!-- Duration of fade in/out animation for attachment previews -->
+ <integer name="ap_fade_animation_duration">500</integer>
<!-- Duration of placeholder pulse animation for attachment previews -->
<integer name="ap_placeholder_animation_duration">2000</integer>
<!-- Delay before showing progress bar animations for attachment previews that are loading -->
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index 60c1133fb..a51fd1d43 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -153,6 +153,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private static int sSendersTextColorRead;
private static int sSendersTextColorUnread;
private static int sDateTextColor;
+ private static int sAttachmentPreviewsBackgroundColor;
private static int sOverflowBadgeColor;
private static int sOverflowTextColor;
private static int sStarTouchSlop;
@@ -163,6 +164,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private static int sSlideAnimationDuration;
private static int sAnimatingBackgroundColor;
private static int sProgressAnimationDuration;
+ private static int sFadeAnimationDuration;
private static float sPlaceholderAnimationDurationRatio;
private static int sProgressAnimationDelay;
private static Interpolator sPulseAnimationInterpolator;
@@ -237,12 +239,18 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
* this animator does not remove the progress bars.
*/
private final ObjectAnimator mProgressAnimator;
+ private final ObjectAnimator mFadeAnimator0;
+ private final ObjectAnimator mFadeAnimator1;
private long mProgressAnimatorCancelledTime;
/** Range from 0.0f to 1.0f. */
private float mAnimatedProgressFraction;
- private int[] mImagesLoaded = new int[0];
+ private float mAnimatedFadeFraction0;
+ private float mAnimatedFadeFraction1;
+ private int[] mImageLoadStatuses = new int[0];
private boolean mShowProgressBar;
- private Runnable mSetShowProgressBarRunnable;
+ private final Runnable mCancelProgressAnimatorRunnable;
+ private final Runnable mSetShowProgressBarRunnable0;
+ private final Runnable mSetShowProgressBarRunnable1;
private static final boolean CONVLIST_ATTACHMENT_PREVIEWS_ENABLED = true;
static {
@@ -465,6 +473,7 @@ 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);
+ sAttachmentPreviewsBackgroundColor = res.getColor(color.ap_background_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);
@@ -482,6 +491,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
sContactPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
sAttachmentPreviewsManager = new AttachmentPreviewsManager(context);
sProgressAnimationDuration = res.getInteger(integer.ap_progress_animation_duration);
+ sFadeAnimationDuration = res.getInteger(integer.ap_fade_animation_duration);
final int placeholderAnimationDuration = res
.getInteger(integer.ap_placeholder_animation_duration);
sPlaceholderAnimationDurationRatio = sProgressAnimationDuration
@@ -527,12 +537,45 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
});
mProgressAnimator = createProgressAnimator();
- mSetShowProgressBarRunnable = new Runnable() {
+ mFadeAnimator0 = createFadeAnimator(0);
+ mFadeAnimator1 = createFadeAnimator(1);
+ mCancelProgressAnimatorRunnable = new Runnable() {
@Override
public void run() {
- LogUtils.v(LOG_TAG, "progress bar: >>> set to true");
- // It's OK to set this field to true when the status is no longer LOADING.
+ if (mProgressAnimator.isStarted() && areAllImagesLoaded()) {
+ LogUtils.v(LOG_TAG, "progress animator: << stopped");
+ mProgressAnimator.cancel();
+ }
+ }
+ };
+ mSetShowProgressBarRunnable0 = new Runnable() {
+ @Override
+ public void run() {
+ if (mImageLoadStatuses.length <= 0
+ || mImageLoadStatuses[0] != PhotoManager.STATUS_LOADING) {
+ return;
+ }
+ LogUtils.v(LOG_TAG, "progress bar 0: >>> set to true");
+ mShowProgressBar = true;
+ if (mFadeAnimator0.isStarted()) {
+ mFadeAnimator0.cancel();
+ }
+ mFadeAnimator0.start();
+ }
+ };
+ mSetShowProgressBarRunnable1 = new Runnable() {
+ @Override
+ public void run() {
+ if (mImageLoadStatuses.length <= 1
+ || mImageLoadStatuses[1] != PhotoManager.STATUS_LOADING) {
+ return;
+ }
+ LogUtils.v(LOG_TAG, "progress bar 1: >>> set to true");
mShowProgressBar = true;
+ if (mFadeAnimator1.isStarted()) {
+ mFadeAnimator1.cancel();
+ }
+ mFadeAnimator1.start();
}
};
Utils.traceEndSection();
@@ -600,8 +643,8 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
mSwipeEnabled = swipeEnabled;
mAdapter = adapter;
final int attachmentPreviewsSize = mHeader.conversation.getAttachmentPreviewUris().size();
- if (attachmentPreviewsChanged || mImagesLoaded.length != attachmentPreviewsSize) {
- mImagesLoaded = new int[attachmentPreviewsSize];
+ if (attachmentPreviewsChanged || mImageLoadStatuses.length != attachmentPreviewsSize) {
+ mImageLoadStatuses = new int[attachmentPreviewsSize];
}
if (checkboxOrSenderImage == ConversationListIcon.SENDER_IMAGE) {
@@ -723,8 +766,13 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
super.onLayout(changed, left, top, right, bottom);
+ Utils.traceBeginSection("text and bitmaps");
calculateTextsAndBitmaps();
+ Utils.traceEndSection();
+
+ Utils.traceBeginSection("coordinates");
calculateCoordinates();
+ Utils.traceEndSection();
// Subject.
createSubject(mHeader.unread);
@@ -938,7 +986,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
uri);
int bestAvailableRendition = -1;
// BEST first, else use less preferred renditions
- for (int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
+ for (final int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
if (Attachment.getPreviewState(previewStates, i, rendition)) {
bestAvailableRendition = rendition;
break;
@@ -969,8 +1017,6 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
Utils.traceEndSection();
Utils.traceBeginSection("start animator");
- // We want to show default progress image
- setImageLoaded(i, PhotoManager.STATUS_NOT_LOADED);
if (!mProgressAnimator.isStarted()) {
LogUtils.v(LOG_TAG, "progress animator: >> started");
// Reduce progress bar stutter caused by reset()/bind() being called multiple
@@ -984,6 +1030,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
LogUtils.v(LOG_TAG, "progress animator: correction for dt %d, fraction %f",
dt, passedFraction);
}
+ removeCallbacks(mCancelProgressAnimatorRunnable);
mProgressAnimator.start();
// Wow.. this must be called after start().
mProgressAnimator.setCurrentPlayTime((long) (sProgressAnimationDuration * (
@@ -1014,12 +1061,12 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
"loadAttachmentPreviews: <= onImageDrawn callback [%b] on index %d for %s", success,
index, key);
// We want to hide the spinning progress bar when we draw something.
- setImageLoaded(index,
+ onImageLoadStatusChanged(index,
success ? PhotoManager.STATUS_LOADED : PhotoManager.STATUS_NOT_LOADED);
if (mProgressAnimator.isStarted() && areAllImagesLoaded()) {
- LogUtils.v(LOG_TAG, "progress animator: << stopped");
- mProgressAnimator.cancel();
+ removeCallbacks(mCancelProgressAnimatorRunnable);
+ postDelayed(mCancelProgressAnimatorRunnable, sFadeAnimationDuration);
}
Utils.traceEndSection();
}
@@ -1035,12 +1082,12 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
LogUtils.v(LOG_TAG,
"loadAttachmentPreviews: <= onImageLoadStarted callback on index %d for %s", index,
key);
- setImageLoaded(index, PhotoManager.STATUS_LOADING);
+ onImageLoadStatusChanged(index, PhotoManager.STATUS_LOADING);
}
private boolean areAllImagesLoaded() {
- for (int i = 0; i < mImagesLoaded.length; i++) {
- if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
+ for (int i = 0; i < mImageLoadStatuses.length; i++) {
+ if (mImageLoadStatuses[i] != PhotoManager.STATUS_LOADED) {
return false;
}
}
@@ -1048,44 +1095,60 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
/**
- * Update the #mImagesLoaded state array with special logic.
+ * Update the #mImageLoadStatuses state array with special logic.
* @param index Which attachment preview's state to update.
* @param status What the new state is.
*/
- private void setImageLoaded(final int index, final int status) {
- if (index < 0 || index >= mImagesLoaded.length) {
+ private void onImageLoadStatusChanged(final int index, final int status) {
+ if (index < 0 || index >= mImageLoadStatuses.length) {
return;
}
- final int prevStatus = mImagesLoaded[index];
+ final int prevStatus = mImageLoadStatuses[index];
+ if (prevStatus == status) {
+ return;
+ }
+
+ boolean changed = false;
switch (status) {
case PhotoManager.STATUS_NOT_LOADED:
+ LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
+ mShowProgressBar = false;
// Cannot transition directly from LOADING to NOT_LOADED.
if (prevStatus != PhotoManager.STATUS_LOADING) {
- mImagesLoaded[index] = status;
+ mImageLoadStatuses[index] = status;
+ changed = true;
}
break;
case PhotoManager.STATUS_LOADING:
// All other statuses must be set to not loading.
- for (int i = 0; i < mImagesLoaded.length; i++) {
- if (i != index && mImagesLoaded[i] == PhotoManager.STATUS_LOADING) {
- mImagesLoaded[i] = PhotoManager.STATUS_NOT_LOADED;
+ for (int i = 0; i < mImageLoadStatuses.length; i++) {
+ if (i != index && mImageLoadStatuses[i] == PhotoManager.STATUS_LOADING) {
+ mImageLoadStatuses[i] = PhotoManager.STATUS_NOT_LOADED;
}
}
- mImagesLoaded[index] = status;
-
- if (prevStatus != PhotoManager.STATUS_LOADING) {
- // Progress bar should only be shown after a delay
- LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
- mShowProgressBar = false;
- LogUtils.v(LOG_TAG, "progress bar: === start delay");
- removeCallbacks(mSetShowProgressBarRunnable);
- postDelayed(mSetShowProgressBarRunnable, sProgressAnimationDelay);
- }
+ mImageLoadStatuses[index] = status;
+
+ // Progress bar should only be shown after a delay
+ LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
+ mShowProgressBar = false;
+ LogUtils.v(LOG_TAG, "progress bar: === start delay");
+ final Runnable setShowProgressBarRunnable = index == 0
+ ? mSetShowProgressBarRunnable0 : mSetShowProgressBarRunnable1;
+ removeCallbacks(setShowProgressBarRunnable);
+ postDelayed(setShowProgressBarRunnable, sProgressAnimationDelay);
+ changed = true;
break;
case PhotoManager.STATUS_LOADED:
- mImagesLoaded[index] = status;
+ mImageLoadStatuses[index] = status;
+ changed = true;
break;
}
+ if (changed) {
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ if (!fadeAnimator.isStarted()) {
+ fadeAnimator.start();
+ }
+ }
}
private static int makeExactSpecForSize(int size) {
@@ -1540,39 +1603,30 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
drawText(canvas, mHeader.overflowText, mOverflowX, mOverflowY, sPaint);
}
- // Progress bar
- if (mProgressAnimator.isRunning()) {
- // Fade from 55 -> 255 -> 55. Each cycle lasts for #sProgressAnimationDuration secs.
- final int maxAlpha = 255, minAlpha = 55;
- final int range = maxAlpha - minAlpha;
- // We want the placeholder to pulse at a different rate from the progressbar to
- // spin.
- final float placeholderAnimFraction = mAnimatedProgressFraction
- * sPlaceholderAnimationDurationRatio;
- // During the time that placeholderAnimFraction takes to go from 0 to 1, we
- // want to go all the way to #maxAlpha and back down to #minAlpha. So from 0 to 0.5,
- // we increase #modifiedProgress from 0 to 1, while from 0.5 to 1 we decrease
- // accordingly from 1 to 0. Math.
- final float modifiedProgress = -2 * Math.abs(placeholderAnimFraction - 0.5f) + 1;
- // Make it feel like a heart beat.
- final float interpolatedProgress = sPulseAnimationInterpolator
- .getInterpolation(modifiedProgress);
- // More math.
- final int alpha = (int) (interpolatedProgress * range + minAlpha);
- sPaint.setAlpha(alpha);
-
- final int count = mImagesLoaded.length;
- for (int i = 0; i < count; i++) {
- if (mShowProgressBar && mImagesLoaded[i] == PhotoManager.STATUS_LOADING) {
- // status is LOADING and enough time has passed
- canvas.save();
- drawProgressBar(canvas, i, count);
- canvas.restore();
- } else if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
- // status is either NOT_LOADED or LOADING
- drawPlaceholder(canvas, i, count);
- }
- }
+ // Placeholders and progress bars
+
+ // Fade from 55 -> 255 -> 55. Each cycle lasts for #sProgressAnimationDuration secs.
+ final int maxAlpha = 255, minAlpha = 55;
+ final int range = maxAlpha - minAlpha;
+ // We want the placeholder to pulse at a different rate from the progressbar to
+ // spin.
+ final float placeholderAnimFraction = mAnimatedProgressFraction
+ * sPlaceholderAnimationDurationRatio;
+ // During the time that placeholderAnimFraction takes to go from 0 to 1, we
+ // want to go all the way to #maxAlpha and back down to #minAlpha. So from 0 to 0.5,
+ // we increase #modifiedProgress from 0 to 1, while from 0.5 to 1 we decrease
+ // accordingly from 1 to 0. Math.
+ final float modifiedProgress = -2 * Math.abs(placeholderAnimFraction - 0.5f) + 1;
+ // Make it feel like a heart beat.
+ final float interpolatedProgress = sPulseAnimationInterpolator
+ .getInterpolation(modifiedProgress);
+ // More math.
+ final int pulseAlpha = (int) (interpolatedProgress * range + minAlpha);
+
+ final int count = mImageLoadStatuses.length;
+ for (int i = 0; i < count; i++) {
+ drawPlaceholder(canvas, i, count, pulseAlpha);
+ drawProgressBar(canvas, i, count);
}
}
@@ -1615,16 +1669,47 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
/**
* Draws the specified placeholder 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.
+ * @param index If drawing multiple placeholders, this determines which one we are drawing.
+ * @param total Whether we are drawing multiple placeholders.
+ * @param pulseAlpha The alpha to draw this at.
*/
- private void drawPlaceholder(Canvas canvas, int index, int total) {
- int placeholderX = getPlaceholderX(index, total);
+ private void drawPlaceholder(final Canvas canvas, final int index, final int total,
+ final int pulseAlpha) {
+ final int placeholderX = getAttachmentPreviewXCenter(index, total)
+ - mCoordinates.placeholderWidth / 2;
if (placeholderX == -1) {
return;
}
+ // Set alpha for crossfading effect.
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ final float animatedFadeFraction = index == 0 ? mAnimatedFadeFraction0
+ : mAnimatedFadeFraction1;
+ final boolean notLoaded = mImageLoadStatuses[index] == PhotoManager.STATUS_NOT_LOADED;
+ final boolean loading = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADING;
+ final boolean loaded = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADED;
+ final float fadeAlphaFraction;
+ if (notLoaded) {
+ fadeAlphaFraction = 1.0f;
+ } else if (loading && !mShowProgressBar) {
+ fadeAlphaFraction = 1.0f;
+ } else if (fadeAnimator.isStarted() && (loading && mShowProgressBar
+ || loaded && !mShowProgressBar)) {
+ // Fade to progress bar or fade to image from placeholder
+ fadeAlphaFraction = 1.0f - animatedFadeFraction;
+ } else {
+ fadeAlphaFraction = 0.0f;
+ }
+
+ if (fadeAlphaFraction == 0.0f) {
+ return;
+ }
+ // Draw background
+ drawAttachmentPreviewBackground(canvas, index, total, (int) (255 * fadeAlphaFraction));
+
+ sPaint.setAlpha((int) (pulseAlpha * fadeAlphaFraction));
canvas.drawBitmap(PLACEHOLDER, placeholderX, mCoordinates.placeholderY, sPaint);
}
@@ -1634,62 +1719,114 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
* @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);
+ private void drawProgressBar(final Canvas canvas, final int index, final int total) {
+ final int progressBarX = getAttachmentPreviewXCenter(index, total)
+ - mCoordinates.progressBarWidth / 2;
if (progressBarX == -1) {
return;
}
+ // Set alpha for crossfading effect.
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ final float animatedFadeFraction = index == 0 ? mAnimatedFadeFraction0
+ : mAnimatedFadeFraction1;
+ final boolean loading = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADING;
+ final boolean loaded = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADED;
+ final int fadeAlpha;
+ if (loading && mShowProgressBar) {
+ fadeAlpha = (int) (255 * animatedFadeFraction);
+ } else if (fadeAnimator.isStarted() && (loaded && mShowProgressBar)) {
+ // Fade to image from progress bar
+ fadeAlpha = (int) (255 * (1.0f - animatedFadeFraction));
+ } else {
+ fadeAlpha = 0;
+ }
+
+ if (fadeAlpha == 0) {
+ return;
+ }
+
+ // Draw background
+ drawAttachmentPreviewBackground(canvas, index, total, fadeAlpha);
+
// Set the level from 0 to 10000 to animate the Drawable.
PROGRESS_BAR.setLevel((int) (mAnimatedProgressFraction * 10000));
// canvas.translate() for Bitmaps, setBounds() for Drawables.
PROGRESS_BAR.setBounds(progressBarX, mCoordinates.progressBarY,
progressBarX + mCoordinates.progressBarWidth,
mCoordinates.progressBarY + mCoordinates.progressBarHeight);
+ PROGRESS_BAR.setAlpha(fadeAlpha);
PROGRESS_BAR.draw(canvas);
}
-
/**
- * @see com.android.mail.browse.ConversationItemView#drawProgressBar
+ * Draws the specified attachment previews background on the canvas.
+ * @param canvas The canvas to draw on.
+ * @param index If drawing for multiple attachment previews, this determines for which one's
+ * background we are drawing.
+ * @param total Whether we are drawing for multiple attachment previews.
+ * @param fadeAlpha The alpha to draw this at.
*/
- private void invalidatePlaceholderAndProgressBar(int index, int total) {
- int progressBarX = getProgressBarX(index, total);
- if (progressBarX == -1) {
+ private void drawAttachmentPreviewBackground(final Canvas canvas, final int index,
+ final int total, final int fadeAlpha) {
+ if (total == 0) {
return;
}
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ final int sectionX = getAttachmentPreviewX(index, total);
+ sPaint.setColor(sAttachmentPreviewsBackgroundColor);
+ sPaint.setAlpha(fadeAlpha);
+ canvas.drawRect(sectionX, mCoordinates.attachmentPreviewsY, sectionX + sectionWidth,
+ mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight, sPaint);
+ }
- invalidate(progressBarX, mCoordinates.progressBarY,
- progressBarX + mCoordinates.progressBarWidth,
- mCoordinates.progressBarY + mCoordinates.progressBarHeight);
+ private void invalidateAttachmentPreviews() {
+ final int total = mImageLoadStatuses.length;
+ for (int index = 0; index < total; index++) {
+ invalidateAttachmentPreview(index, total);
+ }
+ }
- int placeholderX = getPlaceholderX(index, total);
- if (placeholderX == -1) {
- return;
+ private void invalidatePlaceholdersAndProgressBars() {
+ final int total = mImageLoadStatuses.length;
+ for (int index = 0; index < total; index++) {
+ invalidatePlaceholderAndProgressBar(index, total);
}
+ }
- invalidate(placeholderX, mCoordinates.placeholderY,
- placeholderX + mCoordinates.placeholderWidth,
- mCoordinates.placeholderY + mCoordinates.placeholderHeight);
+ private void invalidateAttachmentPreview(final int index, final int total) {
+ invalidate(getAttachmentPreviewX(index, total), mCoordinates.attachmentPreviewsY,
+ getAttachmentPreviewX(index + 1, total),
+ mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight);
}
- private int getPlaceholderX(int index, int total) {
- if (mCoordinates == null) {
+ private void invalidatePlaceholderAndProgressBar(final int index, final int total) {
+ final int width = Math.max(mCoordinates.placeholderWidth, mCoordinates.progressBarWidth);
+ final int height = Math.max(mCoordinates.placeholderHeight, mCoordinates.progressBarHeight);
+ final int x = getAttachmentPreviewXCenter(index, total) - width / 2;
+ final int xEnd = getAttachmentPreviewXCenter(index, total) + width / 2;
+ final int yCenter = mCoordinates.attachmentPreviewsY
+ + mCoordinates.attachmentPreviewsHeight / 2;
+ final int y = yCenter - height / 2;
+ final int yEnd = yCenter + height / 2;
+
+ invalidate(x, y, xEnd, yEnd);
+ }
+
+ private int getAttachmentPreviewX(final int index, final int total) {
+ if (mCoordinates == null || total == 0) {
return -1;
}
- int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
- int sectionOffset = index * sectionWidth;
- return mCoordinates.attachmentPreviewsX + sectionOffset + sectionWidth / 2
- - mCoordinates.placeholderWidth / 2;
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ final int sectionOffset = index * sectionWidth;
+ return mCoordinates.attachmentPreviewsX + sectionOffset;
}
- private int getProgressBarX(int index, int total) {
- if (mCoordinates == null) {
+ private int getAttachmentPreviewXCenter(final int index, final int total) {
+ if (total == 0) {
return -1;
}
- int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
- int sectionOffset = index * sectionWidth;
- return mCoordinates.attachmentPreviewsX + sectionOffset + sectionWidth / 2
- - mCoordinates.progressBarWidth / 2;
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ return getAttachmentPreviewX(index, total) + sectionWidth / 2;
}
private Bitmap getStarBitmap() {
@@ -1814,9 +1951,12 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
&& 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);
+ final int total = mHeader.conversation.getAttachmentPreviewUris().size();
+ if (mCoordinates.attachmentPreviewsWidth == 0 || total == 0) {
+ return -1;
+ }
+ final int eachWidth = mCoordinates.attachmentPreviewsWidth / total;
+ final int offset = (int) (x - mCoordinates.attachmentPreviewsX);
return offset / eachWidth;
}
return -1;
@@ -1971,8 +2111,8 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
setTranslationX(0f);
mAnimatedHeightFraction = 1.0f;
if (mProgressAnimator.isStarted()) {
- LogUtils.v(LOG_TAG, "progress animator: << stopped");
- mProgressAnimator.cancel();
+ removeCallbacks(mCancelProgressAnimatorRunnable);
+ postDelayed(mCancelProgressAnimatorRunnable, sFadeAnimationDuration);
}
Utils.traceEndSection();
}
@@ -2069,7 +2209,7 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
private ObjectAnimator createProgressAnimator() {
final ObjectAnimator animator = ObjectAnimator
- .ofFloat(this, "animatedProgressFraction", 0f, 1.0f).setDuration(
+ .ofFloat(this, "animatedProgressFraction", 0.0f, 1.0f).setDuration(
sProgressAnimationDuration);
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatCount(ObjectAnimator.INFINITE);
@@ -2087,10 +2227,27 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
}
private void invalidateAll() {
- final int count = mHeader.conversation.getAttachmentPreviewUris().size();
- for (int i = 0; i < count; i++) {
- invalidatePlaceholderAndProgressBar(i, count);
- }
+ invalidatePlaceholdersAndProgressBars();
+ }
+ });
+ return animator;
+ }
+
+ private ObjectAnimator createFadeAnimator(final int index) {
+ final ObjectAnimator animator = ObjectAnimator
+ .ofFloat(this, "animatedFadeFraction" + index, 0.0f, 1.0f).setDuration(
+ sFadeAnimationDuration);
+ animator.setInterpolator(new DecelerateInterpolator());
+ animator.setRepeatCount(0);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(final Animator animation) {
+ invalidateAttachmentPreview(index, mImageLoadStatuses.length);
+ }
+
+ @Override
+ public void onAnimationCancel(final Animator animation) {
+ invalidateAttachmentPreview(index, mImageLoadStatuses.length);
}
});
return animator;
@@ -2103,12 +2260,19 @@ public class ConversationItemView extends View implements SwipeableItemView, Tog
return;
}
mAnimatedProgressFraction = fraction;
- final int count = mImagesLoaded.length;
- for (int i = 0; i < count; i++) {
- if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
- invalidatePlaceholderAndProgressBar(i, count);
- }
- }
+ invalidatePlaceholdersAndProgressBars();
+ }
+
+ // Used by animator
+ public void setAnimatedFadeFraction0(final float fraction) {
+ mAnimatedFadeFraction0 = fraction;
+ invalidateAttachmentPreview(0, mImageLoadStatuses.length);
+ }
+
+ // Used by animator
+ public void setAnimatedFadeFraction1(final float fraction) {
+ mAnimatedFadeFraction1 = fraction;
+ invalidateAttachmentPreview(1, mImageLoadStatuses.length);
}
@Override
diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
index 543f63657..e234d8826 100644
--- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java
+++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
@@ -465,22 +465,15 @@ public class ConversationItemViewCoordinates {
paperclipPaddingLeft = paperclip.getPaddingLeft();
if (attachmentPreviews != null) {
- attachmentPreviewsX = getAttachmentPreviewsX(attachmentPreviews,
- config.mAttachmentPreviewMode);
+ attachmentPreviewsX = subjectX;
attachmentPreviewsY = getY(attachmentPreviews) + sendersTopAdjust;
- final int attachmentPreviewsXEnd;
- if (isWide()) {
- attachmentPreviewsXEnd = subjectX + subjectWidth;
- } else {
- attachmentPreviewsXEnd = starX + starWidth;
- }
-
- attachmentPreviewsWidth = attachmentPreviewsXEnd - attachmentPreviewsX;
+ attachmentPreviewsWidth = subjectWidth;
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();
+ final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) overflow
+ .getLayoutParams();
overflowXEnd = attachmentPreviewsX + attachmentPreviewsWidth - params.rightMargin;
overflowYEnd = attachmentPreviewsY + attachmentPreviewsHeight - params.bottomMargin;
overflowDiameter = overflow.getWidth();
@@ -558,15 +551,9 @@ public class ConversationItemViewCoordinates {
}
}
- private int getAttachmentPreviewsX(View attachmentPreviews, int attachmentPreviewMode) {
- if (isWide() || attachmentPreviewMode == ATTACHMENT_PREVIEW_READ) {
- return subjectX;
- }
- return getX(attachmentPreviews);
- }
-
- private int getAttachmentPreviewsHeight(Context context, int attachmentPreviewMode) {
- Resources res = context.getResources();
+ private int getAttachmentPreviewsHeight(final Context context,
+ final int attachmentPreviewMode) {
+ final Resources res = context.getResources();
switch (attachmentPreviewMode) {
case ATTACHMENT_PREVIEW_UNREAD:
return (int) (isWide() ? res.getDimension(dimen.attachment_preview_height_tall_wide)
diff --git a/src/com/android/mail/photomanager/PhotoManager.java b/src/com/android/mail/photomanager/PhotoManager.java
index b3037fc98..0b937cb26 100644
--- a/src/com/android/mail/photomanager/PhotoManager.java
+++ b/src/com/android/mail/photomanager/PhotoManager.java
@@ -468,19 +468,15 @@ public abstract class PhotoManager implements ComponentCallbacks2, Callback {
}
case MESSAGE_PHOTOS_LOADED: {
- if (!mPaused) {
- processLoadedImages();
- }
+ processLoadedImages();
if (DEBUG) dumpStats();
return true;
}
case MESSAGE_PHOTO_LOADING: {
- if (!mPaused) {
- final int hashcode = msg.arg1;
- final Request request = mPendingRequests.get(hashcode);
- onImageLoadStarted(request);
- }
+ final int hashcode = msg.arg1;
+ final Request request = mPendingRequests.get(hashcode);
+ onImageLoadStarted(request);
return true;
}
}
@@ -494,9 +490,9 @@ public abstract class PhotoManager implements ComponentCallbacks2, Callback {
private void processLoadedImages() {
Utils.traceBeginSection("process loaded images");
final List<Integer> toRemove = Lists.newArrayList();
- for (Integer hash : mPendingRequests.keySet()) {
- Request request = mPendingRequests.get(hash);
- boolean loaded = loadCachedPhoto(request, true);
+ for (final Integer hash : mPendingRequests.keySet()) {
+ final Request request = mPendingRequests.get(hash);
+ final boolean loaded = loadCachedPhoto(request, true);
// Request can go through multiple attempts if the LoaderThread fails to load any
// images for it, or if the images it loads are evicted from the cache before we
// could access them in the main thread.
@@ -504,11 +500,11 @@ public abstract class PhotoManager implements ComponentCallbacks2, Callback {
toRemove.add(hash);
}
}
- for (Integer key : toRemove) {
+ for (final Integer key : toRemove) {
mPendingRequests.remove(key);
}
- if (!mPendingRequests.isEmpty()) {
+ if (!mPaused && !mPendingRequests.isEmpty()) {
LogUtils.d(TAG, "Finished loading batch. %d still have to be loaded.",
mPendingRequests.size());
requestLoading();
diff --git a/src/com/android/mail/ui/SwipeableListView.java b/src/com/android/mail/ui/SwipeableListView.java
index 652365451..c8d36bd2c 100644
--- a/src/com/android/mail/ui/SwipeableListView.java
+++ b/src/com/android/mail/ui/SwipeableListView.java
@@ -79,11 +79,11 @@ public class SwipeableListView extends ListView implements Callback, OnScrollLis
public SwipeableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ setOnScrollListener(this);
float densityScale = getResources().getDisplayMetrics().density;
float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale,
pagingTouchSlop);
- setOnScrollListener(this);
}
@Override