ConversationItemView.java revision 850c55ee2cab6b1c224366c66502f5d5f55018eb
15e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal/* 25e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * Copyright (C) 2012 Google Inc. 35e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * Licensed to The Android Open Source Project. 46f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 56f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 66f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * you may not use this file except in compliance with the License. 76f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * You may obtain a copy of the License at 86f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 95e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * http://www.apache.org/licenses/LICENSE-2.0 106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * Unless required by applicable law or agreed to in writing, software 126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * See the License for the specific language governing permissions and 156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * limitations under the License. 166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira */ 175e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal 1830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.browse; 196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 20bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereiraimport android.animation.Animator; 21304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport android.animation.Animator.AnimatorListener; 22bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereiraimport android.animation.AnimatorSet; 23866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.animation.ObjectAnimator; 24304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport android.content.Context; 256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.content.res.Resources; 26f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereiraimport android.database.Cursor; 276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Bitmap; 286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.BitmapFactory; 296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Canvas; 306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Color; 31b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.LinearGradient; 32b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.Paint; 336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Rect; 34b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.Shader; 356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Typeface; 366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.drawable.Drawable; 376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Layout.Alignment; 386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Spannable; 39b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereiraimport android.text.SpannableString; 406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.SpannableStringBuilder; 416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.StaticLayout; 426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextPaint; 436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils; 446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils.TruncateAt; 456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.format.DateUtils; 466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.CharacterStyle; 476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.ForegroundColorSpan; 486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.StyleSpan; 496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.util.SparseArray; 50850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.Gravity; 516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.MotionEvent; 526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.View; 53850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.ViewGroup; 54850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.ViewGroup.LayoutParams; 55866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.view.animation.DecelerateInterpolator; 56f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blankimport android.widget.ListView; 57850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.widget.TextView; 586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 59732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.R; 60732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.browse.ConversationItemViewModel.SenderFragment; 61732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.perf.Timer; 62732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.providers.Conversation; 63b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.providers.Folder; 643cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereiraimport com.android.mail.providers.UIProvider; 65c8a994227b9c686d88ee05840544162711a85712Marc Blankimport com.android.mail.providers.UIProvider.ConversationColumns; 66bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.ui.AnimatedAdapter; 67e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereiraimport com.android.mail.ui.ControllableActivity; 681ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.ui.ConversationSelectionSet; 69b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.ui.FolderDisplayer; 706c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport com.android.mail.ui.SwipeableItemView; 71a538984fcc19e7624f2650b119ede39bf1f35846mindypimport com.android.mail.ui.SwipeableListView; 721ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.ui.ViewMode; 732f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwalimport com.android.mail.utils.LogTag; 74732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.utils.Utils; 75304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport com.google.common.annotations.VisibleForTesting; 76732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang 776c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereirapublic class ConversationItemView extends View implements SwipeableItemView { 786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Timer. 796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static int sLayoutCount = 0; 80bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook private static Timer sTimer; // Create the sTimer here if you need to do 81bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // perf analysis. 826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final int PERF_LAYOUT_ITERATIONS = 50; 836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_LAYOUT = "CCHV.layout"; 846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_TEXTS_BITMAPS = "CCHV.txtsbmps"; 856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_SENDER_SUBJECT = "CCHV.sendersubj"; 8630fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira private static final String PERF_TAG_CALCULATE_FOLDERS = "CCHV.folders"; 876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_COORDINATES = "CCHV.coordinates"; 882f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwal private static final String LOG_TAG = LogTag.getLogTag(); 896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static bitmaps. 916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap CHECKMARK_OFF; 926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap CHECKMARK_ON; 936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap STAR_OFF; 946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap STAR_ON; 956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap ATTACHMENT; 966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap ONLY_TO_ME; 976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap TO_ME_AND_OTHERS; 986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap IMPORTANT_ONLY_TO_ME; 996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap IMPORTANT_TO_ME_AND_OTHERS; 1006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap IMPORTANT_TO_OTHERS; 1016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap DATE_BACKGROUND; 10254467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_REPLIED; 10354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_FORWARDED; 10454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_REPLIED_AND_FORWARDED; 1058d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira private static Bitmap STATE_CALENDAR_INVITE; 1066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 107ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static String sSendersSplitToken; 108ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static String sElidedPaddingToken; 10984cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira private static String sEllipsis; 11024538e893ef2db41a4c1b341f676b64422920304Mindy Pereira 1116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static colors. 112ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sDefaultTextColor; 113ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sActivatedTextColor; 114ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSubjectTextColorRead; 115ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSubjectTextColorUnead; 116ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSnippetTextColorRead; 117ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSnippetTextColorUnread; 118ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSendersTextColorRead; 119ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sSendersTextColorUnread; 120ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sDateTextColor; 121ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sDateBackgroundPaddingLeft; 122ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static int sTouchSlop; 1236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static int sDateBackgroundHeight; 1246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static int sStandardScaledDimen; 125067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private static int sShrinkAnimationDuration; 126067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private static int sSlideAnimationDuration; 127d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira private static int sAnimatingBackgroundColor; 1286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static paints. 1306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static TextPaint sPaint = new TextPaint(); 13130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira private static TextPaint sFoldersPaint = new TextPaint(); 1326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Backgrounds for different states. 1346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>(); 1356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Dimensions and coordinates. 1376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mViewWidth = -1; 1386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mMode = -1; 1396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mDateX; 1406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mPaperclipX; 14130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira private int mFoldersXEnd; 1426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mSendersWidth; 1436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira /** Whether we're running under test mode. */ 1456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private boolean mTesting = false; 146fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal /** Whether we are on a tablet device or not */ 147fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal private final boolean mTabletDevice; 1486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @VisibleForTesting 1500944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira ConversationItemViewCoordinates mCoordinates; 1516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private final Context mContext; 1536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 154866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public ConversationItemViewModel mHeader; 155c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira private boolean mDownEvent; 156d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal private boolean mChecked = false; 1576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static int sFadedActivatedColor = -1; 15811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira private ConversationSelectionSet mSelectedConversationSet; 1594584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira private Folder mDisplayedFolder; 1603cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira private boolean mPriorityMarkersEnabled; 161b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira private boolean mCheckboxesEnabled; 162f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira private boolean mSwipeEnabled; 163bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook private AnimatedAdapter mAdapter; 164bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira private int mAnimatedHeight = -1; 165c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira private String mAccount; 166e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira private ControllableActivity mActivity; 1678a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira private CharacterStyle mActivatedTextSpan; 1685c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira private int mBackgroundOverride = -1; 169850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp private static int sSendersTextViewTopPadding; 170850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp private static int sSendersTextViewHeight; 1718a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira private static ForegroundColorSpan sActivatedTextSpan; 172fb7bace9a83abf0e8726def19e76cb03afdf5740Mindy Pereira private static Bitmap sDateBackgroundAttachment; 173fb7bace9a83abf0e8726def19e76cb03afdf5740Mindy Pereira private static Bitmap sDateBackgroundNoAttachment; 174350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira private static int sUndoAnimationOffset; 175b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private static Bitmap MORE_FOLDERS; 1766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira static { 1786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setAntiAlias(true); 17930fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira sFoldersPaint.setAntiAlias(true); 1806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 1816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 182b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira /** 183b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira * Handles displaying folders in a conversation header view. 184b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira */ 185b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira static class ConversationItemFolderDisplayer extends FolderDisplayer { 186b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Maximum number of folders to be displayed. 187b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private static final int MAX_DISPLAYED_FOLDERS_COUNT = 4; 188b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 189b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private int mFoldersCount; 190b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private boolean mHasMoreFolders; 191b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 192c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang public ConversationItemFolderDisplayer(Context context) { 193c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang super(context); 194c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang } 195c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang 196b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira @Override 19785c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira public void loadConversationFolders(Conversation conv, Folder ignoreFolder) { 19885c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira super.loadConversationFolders(conv, ignoreFolder); 199b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 200c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang mFoldersCount = mFoldersSortedSet.size(); 201b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mHasMoreFolders = mFoldersCount > MAX_DISPLAYED_FOLDERS_COUNT; 202b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mFoldersCount = Math.min(mFoldersCount, MAX_DISPLAYED_FOLDERS_COUNT); 203b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 204b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 205b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira public boolean hasVisibleFolders() { 206b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return mFoldersCount > 0; 207b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 208b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 209b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private int measureFolders(int mode) { 210b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int availableSpace = ConversationItemViewCoordinates.getFoldersWidth(mContext, mode); 211b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int cellSize = ConversationItemViewCoordinates.getFolderCellWidth(mContext, mode, 212b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mFoldersCount); 213b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 214b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int totalWidth = 0; 215c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang for (Folder f : mFoldersSortedSet) { 216c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang final String folderString = f.name; 217c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang int width = (int) sFoldersPaint.measureText(folderString) + cellSize; 218b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (width % cellSize != 0) { 219b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira width += cellSize - (width % cellSize); 220b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 221b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira totalWidth += width; 222b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (totalWidth > availableSpace) { 223b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira break; 224b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 225b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 226b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 227b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return totalWidth; 228b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 229b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 230b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira public void drawFolders(Canvas canvas, ConversationItemViewCoordinates coordinates, 231b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int foldersXEnd, int mode) { 232b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mFoldersCount == 0) { 233b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return; 234b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 235b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 236b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int xEnd = foldersXEnd; 237b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int y = coordinates.foldersY - coordinates.foldersAscent; 238b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int height = coordinates.foldersHeight; 239b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int topPadding = coordinates.foldersTopPadding; 240b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int ascent = coordinates.foldersAscent; 241b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira sFoldersPaint.setTextSize(coordinates.foldersFontSize); 242b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 243b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Initialize space and cell size based on the current mode. 244b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int availableSpace = ConversationItemViewCoordinates.getFoldersWidth(mContext, mode); 245b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int averageWidth = availableSpace / mFoldersCount; 246b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int cellSize = ConversationItemViewCoordinates.getFolderCellWidth(mContext, mode, 247b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mFoldersCount); 248b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 249b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // First pass to calculate the starting point. 250b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int totalWidth = measureFolders(mode); 251b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int xStart = xEnd - Math.min(availableSpace, totalWidth); 252b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 253b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Second pass to draw folders. 254c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang for (Folder f : mFoldersSortedSet) { 255c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang final String folderString = f.name; 256c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang final int fgColor = f.getForegroundColor(mDefaultFgColor); 257c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang final int bgColor = f.getBackgroundColor(mDefaultBgColor); 258b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int width = cellSize; 259b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira boolean labelTooLong = false; 260c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang width = (int) sFoldersPaint.measureText(folderString) + cellSize; 261b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (width % cellSize != 0) { 262b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira width += cellSize - (width % cellSize); 263b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 264b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (totalWidth > availableSpace && width > averageWidth) { 265b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira width = averageWidth; 266a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira labelTooLong = true; 267b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 268b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 269b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // TODO (mindyp): how to we get this? 270b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira final boolean isMuted = false; 271bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // labelValues.folderId == 272bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // sGmail.getFolderMap(mAccount).getFolderIdIgnored(); 273b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 274b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Draw the box. 275c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang sFoldersPaint.setColor(bgColor); 276b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira sFoldersPaint.setStyle(isMuted ? Paint.Style.STROKE : Paint.Style.FILL_AND_STROKE); 277b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira canvas.drawRect(xStart, y + ascent, xStart + width, y + ascent + height, 278b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira sFoldersPaint); 279b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 280b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Draw the text. 281c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang int padding = getPadding(width, (int) sFoldersPaint.measureText(folderString)); 282b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (labelTooLong) { 283a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira TextPaint shortPaint = new TextPaint(); 284a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira shortPaint.setColor(fgColor); 285a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira shortPaint.setTextSize(coordinates.foldersFontSize); 286b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira padding = cellSize / 2; 287b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira int rightBorder = xStart + width - padding; 288b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira Shader shader = new LinearGradient(rightBorder - padding, y, rightBorder, y, 289a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira fgColor, Utils.getTransparentColor(fgColor), Shader.TileMode.CLAMP); 290a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira shortPaint.setShader(shader); 291a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira canvas.drawText(folderString, xStart + padding, y + topPadding, shortPaint); 292a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira } else { 293a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira sFoldersPaint.setColor(fgColor); 294a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira canvas.drawText(folderString, xStart + padding, y + topPadding, sFoldersPaint); 295b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 296b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 297b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira availableSpace -= width; 298b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira xStart += width; 299b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (availableSpace <= 0 && mHasMoreFolders) { 300b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira canvas.drawBitmap(MORE_FOLDERS, xEnd, y + ascent, sFoldersPaint); 301b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return; 302b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 303b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 304b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 305acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira } 306b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 307acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira /** 308acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira * Helpers function to align an element in the center of a space. 309acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira */ 310acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira private static int getPadding(int space, int length) { 311acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira return (space - length) / 2; 312b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 313b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 3140944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira public ConversationItemView(Context context, String account) { 3156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira super(context); 316960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira setClickable(true); 317960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira setLongClickable(true); 3186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mContext = context.getApplicationContext(); 319fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal mTabletDevice = Utils.useTabletUI(mContext); 320c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira mAccount = account; 3216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Resources res = mContext.getResources(); 3226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 3236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (CHECKMARK_OFF == null) { 3246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize static bitmaps. 3256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira CHECKMARK_OFF = BitmapFactory.decodeResource(res, 3266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.btn_check_off_normal_holo_light); 3276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira CHECKMARK_ON = BitmapFactory.decodeResource(res, 3286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.btn_check_on_normal_holo_light); 3296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira STAR_OFF = BitmapFactory.decodeResource(res, 3306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.btn_star_off_normal_email_holo_light); 3316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira STAR_ON = BitmapFactory.decodeResource(res, 3326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.btn_star_on_normal_email_holo_light); 3336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira ONLY_TO_ME = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_double); 3346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_single); 3356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira IMPORTANT_ONLY_TO_ME = BitmapFactory.decodeResource(res, 3366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.ic_email_caret_double_important_unread); 3376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira IMPORTANT_TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, 3386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.ic_email_caret_single_important_unread); 3396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira IMPORTANT_TO_OTHERS = BitmapFactory.decodeResource(res, 3406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.drawable.ic_email_caret_none_important_unread); 3416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attachment_holo_light); 342b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira MORE_FOLDERS = BitmapFactory.decodeResource(res, R.drawable.ic_folders_more); 343e9a81035bcef5a372fa13a992f8553eb60e6aaf0Vikram Aggarwal DATE_BACKGROUND = BitmapFactory.decodeResource(res, R.drawable.folder_bg_holo_light); 34454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_REPLIED = 34554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_holo_light); 34654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_FORWARDED = 34754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_forward_holo_light); 34854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_REPLIED_AND_FORWARDED = 34954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_forward_holo_light); 3508d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira STATE_CALENDAR_INVITE = 3518d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_invite_holo_light); 3526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 3536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize colors. 354ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sDefaultTextColor = res.getColor(R.color.default_text_color); 355ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sActivatedTextColor = res.getColor(android.R.color.white); 3568a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira sActivatedTextSpan = new ForegroundColorSpan(sActivatedTextColor); 357ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSubjectTextColorRead = res.getColor(R.color.subject_text_color_read); 358ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSubjectTextColorUnead = res.getColor(R.color.subject_text_color_unread); 359ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSnippetTextColorRead = res.getColor(R.color.snippet_text_color_read); 360ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSnippetTextColorUnread = res.getColor(R.color.snippet_text_color_unread); 361ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSendersTextColorRead = res.getColor(R.color.senders_text_color_read); 362ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSendersTextColorUnread = res.getColor(R.color.senders_text_color_unread); 363ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sDateTextColor = res.getColor(R.color.date_text_color); 364ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sDateBackgroundPaddingLeft = res 3656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira .getDimensionPixelSize(R.dimen.date_background_padding_left); 366ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sTouchSlop = res.getDimensionPixelSize(R.dimen.touch_slop); 3676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height); 3686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sStandardScaledDimen = res.getDimensionPixelSize(R.dimen.standard_scaled_dimen); 369067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira sShrinkAnimationDuration = res.getInteger(R.integer.shrink_animation_duration); 370067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira sSlideAnimationDuration = res.getInteger(R.integer.slide_animation_duration); 371350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira sUndoAnimationOffset = res.getDimensionPixelOffset(R.dimen.undo_animation_offset); 3726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize static color. 373ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSendersSplitToken = res.getString(R.string.senders_split_token); 374ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sElidedPaddingToken = res.getString(R.string.elided_padding_token); 37584cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira sEllipsis = res.getString(R.string.ellipsis); 376d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira sAnimatingBackgroundColor = res.getColor(R.color.animating_item_background_color); 377850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sSendersTextViewTopPadding = res.getDimensionPixelSize 378850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp (R.dimen.senders_textview_top_padding); 379850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sSendersTextViewHeight = res.getDimensionPixelSize 380850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp (R.dimen.senders_textview_height); 3816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 3826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 3836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 384e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira public void bind(Cursor cursor, ControllableActivity activity, ConversationSelectionSet set, 385e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira Folder folder, boolean checkboxesDisabled, boolean swipeEnabled, 386e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira boolean priorityArrowEnabled, AnimatedAdapter adapter) { 387e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira bind(ConversationItemViewModel.forCursor(mAccount, cursor), activity, set, folder, 38833519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal checkboxesDisabled, swipeEnabled, priorityArrowEnabled, adapter); 389b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira } 390b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira 391e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira public void bind(Conversation conversation, ControllableActivity activity, 392e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira ConversationSelectionSet set, Folder folder, boolean checkboxesDisabled, 393e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) { 394e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira bind(ConversationItemViewModel.forConversation(mAccount, conversation), activity, set, 39533519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal folder, checkboxesDisabled, swipeEnabled, priorityArrowEnabled, adapter); 396acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira } 397acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira 398e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira private void bind(ConversationItemViewModel header, ControllableActivity activity, 399acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira ConversationSelectionSet set, Folder folder, boolean checkboxesDisabled, 40033519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) { 401acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira mHeader = header; 402e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira mActivity = activity; 403b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira mSelectedConversationSet = set; 404b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira mDisplayedFolder = folder; 40590fc0ffa0ad4fcde94fa9648df7f8041bfb6a943Mindy Pereira mCheckboxesEnabled = !checkboxesDisabled; 406f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira mSwipeEnabled = swipeEnabled; 40733519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal mPriorityMarkersEnabled = priorityArrowEnabled; 408bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook mAdapter = adapter; 409f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira setContentDescription(mHeader.getContentDescription(mContext)); 410f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira requestLayout(); 411f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira } 412f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira 413866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 414866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Get the Conversation object associated with this view. 415866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 416732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang public Conversation getConversation() { 417732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang return mHeader.conversation; 418732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang } 419732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang 4206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira /** 4216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * Sets the mode. Only used for testing. 4226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira */ 4236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @VisibleForTesting 4246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira void setMode(int mode) { 4256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mMode = mode; 4266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mTesting = true; 4276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static void startTimer(String tag) { 4306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null) { 4316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.start(tag); 4326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static void pauseTimer(String tag) { 4366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null) { 4376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.pause(tag); 4386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 4426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 4436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_LAYOUT); 4446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira super.onLayout(changed, left, top, right, bottom); 4466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int width = right - left; 4486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (width != mViewWidth) { 4496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mViewWidth = width; 4506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (!mTesting) { 451e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira mMode = ConversationItemViewCoordinates.getMode(mContext, mActivity.getViewMode()); 4526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.viewWidth = mViewWidth; 4556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Resources res = getResources(); 4566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen); 4576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.standardScaledDimen != sStandardScaledDimen) { 4586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Large Text has been toggle on/off. Update the static dimens. 4596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sStandardScaledDimen = mHeader.standardScaledDimen; 4600944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira ConversationItemViewCoordinates.refreshConversationHeights(mContext); 4616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height); 4626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4630944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira mCoordinates = ConversationItemViewCoordinates.forWidth(mContext, mViewWidth, mMode, 4646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.standardScaledDimen); 4656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira calculateTextsAndBitmaps(); 4666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira calculateCoordinates(); 4676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.validate(mContext); 4686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_LAYOUT); 4706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null && ++sLayoutCount >= PERF_LAYOUT_ITERATIONS) { 4716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.dumpResults(); 4726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer = new Timer(); 4736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sLayoutCount = 0; 4746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 4786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira public void setBackgroundResource(int resourceId) { 4796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Drawable drawable = mBackgrounds.get(resourceId); 4806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (drawable == null) { 4816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira drawable = getResources().getDrawable(resourceId); 4826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mBackgrounds.put(resourceId, drawable); 4836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (getBackground() != drawable) { 4856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira super.setBackgroundDrawable(drawable); 4866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void calculateTextsAndBitmaps() { 4906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 491d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal if (mSelectedConversationSet != null) { 492d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal mChecked = mSelectedConversationSet.contains(mHeader.conversation); 493d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal } 4946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Update font color. 495ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int fontColor = getFontColor(sDefaultTextColor); 4966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira boolean fontChanged = false; 4976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.fontColor != fontColor) { 4986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira fontChanged = true; 4996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.fontColor = fontColor; 5006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5028d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank boolean isUnread = mHeader.unread; 5036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 504b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira final boolean checkboxEnabled = mCheckboxesEnabled; 5056f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.checkboxVisible != checkboxEnabled) { 5066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.checkboxVisible = checkboxEnabled; 5076f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5096f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Update background. 5106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira updateBackground(isUnread); 5116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.isLayoutValid(mContext)) { 5136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Relayout subject if font color has changed. 5146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (fontChanged) { 5150b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira layoutSubjectSpans(isUnread); 5166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira layoutSubject(); 5178a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira layoutSenderSpans(); 5186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 5206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return; 5216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 52330fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira startTimer(PERF_TAG_CALCULATE_FOLDERS); 524b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 525b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Initialize folder displayer. 526b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mCoordinates.showFolders) { 527c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang mHeader.folderDisplayer = new ConversationItemFolderDisplayer(mContext); 52885c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira mHeader.folderDisplayer.loadConversationFolders(mHeader.conversation, mDisplayedFolder); 529b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 530b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 53130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira pauseTimer(PERF_TAG_CALCULATE_FOLDERS); 5326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 533732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang mHeader.dateText = DateUtils.getRelativeTimeSpanString(mContext, 534732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang mHeader.conversation.dateMs).toString(); 5356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Paper clip icon. 5376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.paperclip = null; 538732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang if (mHeader.conversation.hasAttachments) { 5396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.paperclip = ATTACHMENT; 5406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Personal level. 5426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.personalLevelBitmap = null; 5433cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira if (mCoordinates.showPersonalLevel) { 544583eea0562dff158bdd3db9c2adfaec9b7ebef68Mindy Pereira final int personalLevel = mHeader.conversation.personalLevel; 5453cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira final boolean isImportant = 546583eea0562dff158bdd3db9c2adfaec9b7ebef68Mindy Pereira mHeader.conversation.priority == UIProvider.ConversationPriority.IMPORTANT; 54733519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal final boolean useImportantMarkers = isImportant && mPriorityMarkersEnabled; 5483cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira 5493cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira if (personalLevel == UIProvider.ConversationPersonalLevel.ONLY_TO_ME) { 5503cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_ONLY_TO_ME 5513cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira : ONLY_TO_ME; 5523cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira } else if (personalLevel == UIProvider.ConversationPersonalLevel.TO_ME_AND_OTHERS) { 5533cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_TO_ME_AND_OTHERS 5543cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira : TO_ME_AND_OTHERS; 5553cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira } else if (useImportantMarkers) { 5563cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira mHeader.personalLevelBitmap = IMPORTANT_TO_OTHERS; 5573cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira } 5583cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira } 5596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT); 5616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Subject. 5630b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira layoutSubjectSpans(isUnread); 5646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 565d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang mHeader.sendersDisplayText = new SpannableStringBuilder(); 5666c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira mHeader.styledSendersString = new SpannableStringBuilder(); 567d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang 5686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Parse senders fragments. 569c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira if (mHeader.conversation.conversationInfo != null) { 570b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira Context context = getContext(); 571b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira mHeader.messageInfoString = SendersView 572b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira .createMessageInfo(context, mHeader.conversation); 573b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int maxChars = ConversationItemViewCoordinates.getSubjectLength(context, 574e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira ConversationItemViewCoordinates.getMode(context, mActivity.getViewMode()), 575b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira mHeader.folderDisplayer != null && mHeader.folderDisplayer.mFoldersCount > 0, 576b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira mHeader.conversation.hasAttachments); 577b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira mHeader.styledSenders = SendersView.format(context, 578b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira mHeader.conversation.conversationInfo, mHeader.messageInfoString.toString(), 579b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira maxChars); 580c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira } else { 58177d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira SendersView.formatSenders(mHeader, getContext()); 582c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira } 5836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT); 5856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 5866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 5876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 5888a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira private void layoutSenderSpans() { 5898a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira if (isActivated() && showActivatedText()) { 5908a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira if (mActivatedTextSpan == null) { 5918a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira mActivatedTextSpan = getActivatedTextSpan(); 5928a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira } 5938a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira mHeader.styledSendersString.setSpan(mActivatedTextSpan, 0, 5948a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira mHeader.styledMessageInfoStringOffset, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 5958a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira } else { 5968a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira mHeader.styledSendersString.removeSpan(mActivatedTextSpan); 5978a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira } 598850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mHeader.sendersTextView = getSendersTextView(); 599850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp } 600850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp 601850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp private TextView getSendersTextView() { 602850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp TextView sendersTextView = new TextView(mContext); 603850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sendersTextView.setMaxLines(1); 604850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sendersTextView.setEllipsize(TextUtils.TruncateAt.END); 605850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sendersTextView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 606850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp ViewGroup.LayoutParams.WRAP_CONTENT)); 607ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp int length = (int) sPaint.measureText(mHeader.styledSendersString.toString()); 608850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sendersTextView.setText(mHeader.styledSendersString, TextView.BufferType.SPANNABLE); 609850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sendersTextView.setWidth(length); 610850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp return sendersTextView; 6118a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira } 6128a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira 6138a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira private CharacterStyle getActivatedTextSpan() { 6148a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira return CharacterStyle.wrap(sActivatedTextSpan); 6158a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira } 6168a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira 6170b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira private void layoutSubjectSpans(boolean isUnread) { 6180b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira if (showActivatedText()) { 6190b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mHeader.subjectTextActivated = createSubject(isUnread, true); 6200b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 6210b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mHeader.subjectText = createSubject(isUnread, false); 6220b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 6230b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira 6240b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira private SpannableStringBuilder createSubject(boolean isUnread, boolean activated) { 625732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang final String subject = filterTag(mHeader.conversation.subject); 626aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira final String snippet = mHeader.conversation.getSnippet(); 627ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int subjectColor = activated ? sActivatedTextColor : isUnread ? sSubjectTextColorUnead 628ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira : sSubjectTextColorRead; 629ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int snippetColor = activated ? sActivatedTextColor : isUnread ? sSnippetTextColorUnread 630ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira : sSnippetTextColorRead; 631bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira SpannableStringBuilder subjectText = Conversation.getSubjectAndSnippetForDisplay(mContext, 632bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira subject, snippet); 6336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (isUnread) { 6340b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira subjectText.setSpan(new StyleSpan(Typeface.BOLD), 0, subject.length(), 6356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 6366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6370b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira subjectText.setSpan(new ForegroundColorSpan(subjectColor), 0, subject.length(), 6380b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 63934775bdefbccd07f194a7e34c2f89e434c1c1ecbAndy Huang if (!TextUtils.isEmpty(snippet)) { 6400b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira subjectText.setSpan(new ForegroundColorSpan(snippetColor), subject.length() + 1, 6410b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira subjectText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 642304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blank } 6430b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira return subjectText; 6446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int getFontColor(int defaultColor) { 647ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira return isActivated() && mTabletDevice ? sActivatedTextColor 6486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira : defaultColor; 6496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6510b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira private boolean showActivatedText() { 6520b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira return mTabletDevice; 6530b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 6540b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira 6556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void layoutSubject() { 6560b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira if (showActivatedText()) { 6570b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mHeader.subjectLayoutActivated = 6580b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira createSubjectLayout(true, mHeader.subjectTextActivated); 6590b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 6600b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mHeader.subjectLayout = createSubjectLayout(false, mHeader.subjectText); 6610b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 6620b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira 6630b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira private StaticLayout createSubjectLayout(boolean activated, 6640b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira SpannableStringBuilder subjectText) { 6656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTextSize(mCoordinates.subjectFontSize); 666ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setColor(activated ? sActivatedTextColor 667ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira : mHeader.unread ? sSubjectTextColorUnead : sSubjectTextColorRead); 6680b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira StaticLayout subjectLayout = new StaticLayout(subjectText, sPaint, 6696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true); 6700b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira int lineCount = subjectLayout.getLineCount(); 6710b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira if (mCoordinates.subjectLineCount < lineCount) { 6720b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira int end = subjectLayout.getLineEnd(mCoordinates.subjectLineCount - 1); 6730b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira subjectLayout = new StaticLayout(subjectText.subSequence(0, end), sPaint, 6740b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true); 6756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6760b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira return subjectLayout; 6776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private boolean canFitFragment(int width, int line, int fixedWidth) { 6806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (line == mCoordinates.sendersLineCount) { 6816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return width + fixedWidth <= mSendersWidth; 6826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 6836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return width <= mSendersWidth; 6846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void calculateCoordinates() { 6886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_COORDINATES); 6896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTextSize(mCoordinates.dateFontSize); 6916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 6926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mDateX = mCoordinates.dateXEnd - (int) sPaint.measureText(mHeader.dateText); 6936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mPaperclipX = mDateX - ATTACHMENT.getWidth(); 6956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 69630fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira int cellWidth = mContext.getResources().getDimensionPixelSize(R.dimen.folder_cell_width); 6976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6983fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira if (ConversationItemViewCoordinates.isWideMode(mMode)) { 6993fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // Folders are displayed above the date. 7003fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira mFoldersXEnd = mCoordinates.dateXEnd; 7013fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // In wide mode, the end of the senders should align with 7023fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // the start of the subject and is based on a max width. 7033fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira mSendersWidth = mCoordinates.sendersWidth; 7043fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira } else { 7053fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // In normal mode, the width is based on where the folders or date 7063fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // (or attachment icon) start. 7073fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira if (mCoordinates.showFolders) { 708b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mHeader.paperclip != null) { 709b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mFoldersXEnd = mPaperclipX; 710b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } else { 711b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mFoldersXEnd = mDateX - cellWidth / 2; 712b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 713b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mSendersWidth = mFoldersXEnd - mCoordinates.sendersX - 2 * cellWidth; 714b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mHeader.folderDisplayer.hasVisibleFolders()) { 715b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mSendersWidth -= ConversationItemViewCoordinates.getFoldersWidth(mContext, 716b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mMode); 717b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 7186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 7193fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira int dateAttachmentStart = 0; 7203fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira // Have this end near the paperclip or date, not the folders. 7213fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira if (mHeader.paperclip != null) { 7223fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira dateAttachmentStart = mPaperclipX; 7233fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira } else { 7243fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira dateAttachmentStart = mDateX; 7253fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira } 7263fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira mSendersWidth = dateAttachmentStart - mCoordinates.sendersX - cellWidth; 7276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 7306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.isLayoutValid(mContext)) { 7316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_COORDINATES); 7326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return; 7336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 7356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Layout subject. 7366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira layoutSubject(); 7376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 7386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Second pass to layout each fragment. 7396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int sendersY = mCoordinates.sendersY - mCoordinates.sendersAscent; 740ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira 741b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira if (mHeader.styledSenders != null) { 742ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira ellipsizeStyledSenders(); 7438a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira layoutSenderSpans(); 744b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } else { 745ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira // First pass to calculate width of each fragment. 746ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int totalWidth = 0; 747ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int fixedWidth = 0; 748ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setTextSize(mCoordinates.sendersFontSize); 749ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 750ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira for (SenderFragment senderFragment : mHeader.senderFragments) { 751ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira CharacterStyle style = senderFragment.style; 752ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int start = senderFragment.start; 753ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int end = senderFragment.end; 754ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira style.updateDrawState(sPaint); 755ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira senderFragment.width = (int) sPaint.measureText(mHeader.sendersText, start, end); 756ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira boolean isFixed = senderFragment.isFixed; 757ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira if (isFixed) { 758ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira fixedWidth += senderFragment.width; 759ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira } 760ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira totalWidth += senderFragment.width; 761ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira } 762ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira 763ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira if (!ConversationItemViewCoordinates.displaySendersInline(mMode)) { 764ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sendersY += totalWidth <= mSendersWidth ? mCoordinates.sendersLineHeight / 2 : 0; 765ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira } 76658ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira totalWidth = ellipsize(fixedWidth, sendersY); 767b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mHeader.sendersDisplayLayout = new StaticLayout(mHeader.sendersDisplayText, sPaint, 768b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mSendersWidth, Alignment.ALIGN_NORMAL, 1, 0, true); 769b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 770b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 771b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira sPaint.setTextSize(mCoordinates.sendersFontSize); 772b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 773b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira if (mSendersWidth < 0) { 774b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mSendersWidth = 0; 775b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 776b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 777b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_COORDINATES); 778b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 779b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 78058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // The rules for displaying ellipsized senders are as follows: 78158ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // 1) If there is message info (either a COUNT or DRAFT info to display), it MUST be shown 78258ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // 2) If senders do not fit, ellipsize the last one that does fit, and stop 78358ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // appending new senders 784ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private int ellipsizeStyledSenders() { 785b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira SpannableStringBuilder builder = new SpannableStringBuilder(); 78684cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira float totalWidth = 0; 787b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira boolean ellipsize = false; 78884cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira float width; 789ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp SpannableStringBuilder messageInfoString = mHeader.messageInfoString; 7900c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira if (messageInfoString.length() > 0) { 7910c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira CharacterStyle[] spans = messageInfoString.getSpans(0, messageInfoString.length(), 7920c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira CharacterStyle.class); 7930c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // There is only 1 character style span; make sure we apply all the 7940c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // styles to the paint object before measuring. 7950c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira if (spans.length > 0) { 7960c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira spans[0].updateDrawState(sPaint); 7970c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira } 7980c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // Paint the message info string to see if we lose space. 7990c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira float messageInfoWidth = sPaint.measureText(messageInfoString.toString()); 8000c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira totalWidth += messageInfoWidth; 8010c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira } 802ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp SpannableString prevSender = null; 803ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp SpannableString ellipsizedText; 804b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira for (SpannableString sender : mHeader.styledSenders) { 805feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira // There may be null sender strings if there were dupes we had to remove. 806feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira if (sender == null) { 807feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira continue; 808feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira } 80958ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // No more width available, we'll only show fixed fragments. 81058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira if (ellipsize) { 81158ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira break; 81258ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira } 8136c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira CharacterStyle[] spans = sender.getSpans(0, sender.length(), CharacterStyle.class); 8146c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira // There is only 1 character style span. 8156c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira if (spans.length > 0) { 8166c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira spans[0].updateDrawState(sPaint); 8176c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira } 8181152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // If there are already senders present in this string, we need to 8191152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // make sure we prepend the dividing token 820b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (SendersView.sElidedString.equals(sender.toString())) { 821b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira prevSender = sender; 822ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sender = copyStyles(spans, sElidedPaddingToken + sender + sElidedPaddingToken); 823b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } else if (builder.length() > 0 824b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira && (prevSender == null || !SendersView.sElidedString.equals(prevSender 825b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira .toString()))) { 826b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira prevSender = sender; 827ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sender = copyStyles(spans, sSendersSplitToken + sender); 828b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } else { 829b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira prevSender = sender; 8301152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira } 831ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp if (spans.length > 0) { 832ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp spans[0].updateDrawState(sPaint); 833ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp } 8341152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // Measure the width of the current sender and make sure we have space 835b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira width = (int) sPaint.measureText(sender.toString()); 836ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira if (width + totalWidth > mSendersWidth) { 837b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira // The text is too long, new line won't help. We have to 838b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira // ellipsize text. 8391152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsize = true; 840ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp width = mSendersWidth - totalWidth; // ellipsis width? 8411152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsizedText = copyStyles(spans, 8421152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira TextUtils.ellipsize(sender, sPaint, width, TruncateAt.END)); 8431152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira width = (int) sPaint.measureText(ellipsizedText.toString()); 8441152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira } else { 8451152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsizedText = null; 846b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 847b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira totalWidth += width; 848b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 849b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira final CharSequence fragmentDisplayText; 850b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira if (ellipsizedText != null) { 851b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira fragmentDisplayText = ellipsizedText; 852b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } else { 8531152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira fragmentDisplayText = sender; 854b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 855b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira builder.append(fragmentDisplayText); 856b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 85701bb8d91c8ea039518ee07c8ac83e4e42cd81739Mindy Pereira mHeader.styledMessageInfoStringOffset = builder.length(); 8588a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira if (messageInfoString != null) { 85958ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira builder.append(messageInfoString); 86058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira } 861b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mHeader.styledSendersString = builder; 86284cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira return (int)totalWidth; 86384cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira } 86484cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira 865d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira private SpannableString copyStyles(CharacterStyle[] spans, CharSequence newText) { 866d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira SpannableString s = new SpannableString(newText); 867d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira if (spans != null && spans.length > 0) { 868d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira s.setSpan(spans[0], 0, s.length(), 0); 869d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira } 870d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira return s; 871d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira } 872d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira 87358ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira private int ellipsize(int fixedWidth, int sendersY) { 874b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira int totalWidth = 0; 8756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int currentLine = 1; 8766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira boolean ellipsize = false; 8776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira for (SenderFragment senderFragment : mHeader.senderFragments) { 8786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira CharacterStyle style = senderFragment.style; 8796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int start = senderFragment.start; 8806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int end = senderFragment.end; 8816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int width = senderFragment.width; 8826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira boolean isFixed = senderFragment.isFixed; 8836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira style.updateDrawState(sPaint); 8846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 8856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // No more width available, we'll only show fixed fragments. 8866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (ellipsize && !isFixed) { 8876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira senderFragment.shouldDisplay = false; 8886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira continue; 8896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 8906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 8916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // New line and ellipsize text if needed. 8926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira senderFragment.ellipsizedText = null; 8936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (isFixed) { 8946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira fixedWidth -= width; 8956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 8966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (!canFitFragment(totalWidth + width, currentLine, fixedWidth)) { 8976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // The text is too long, new line won't help. We have to 8986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // ellipsize text. 8996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (totalWidth == 0) { 9006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira ellipsize = true; 9016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 9026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // New line. 9036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (currentLine < mCoordinates.sendersLineCount) { 9046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira currentLine++; 9056f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sendersY += mCoordinates.sendersLineHeight; 9066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira totalWidth = 0; 9076f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // The text is still too long, we have to ellipsize 9086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // text. 9096f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (totalWidth + width > mSendersWidth) { 9106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira ellipsize = true; 9116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 9136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira ellipsize = true; 9146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (ellipsize) { 9186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira width = mSendersWidth - totalWidth; 9196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // No more new line, we have to reserve width for fixed 9206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // fragments. 9216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (currentLine == mCoordinates.sendersLineCount) { 9226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira width -= fixedWidth; 9236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira senderFragment.ellipsizedText = TextUtils.ellipsize( 9256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.sendersText.substring(start, end), sPaint, width, 9266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira TruncateAt.END).toString(); 9276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira width = (int) sPaint.measureText(senderFragment.ellipsizedText); 9286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira senderFragment.shouldDisplay = true; 9316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira totalWidth += width; 932d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang 933d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang final CharSequence fragmentDisplayText; 934d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang if (senderFragment.ellipsizedText != null) { 935d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang fragmentDisplayText = senderFragment.ellipsizedText; 936d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang } else { 937d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang fragmentDisplayText = mHeader.sendersText.substring(start, end); 938d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang } 939d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang final int spanStart = mHeader.sendersDisplayText.length(); 940d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang mHeader.sendersDisplayText.append(fragmentDisplayText); 941d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang mHeader.sendersDisplayText.setSpan(senderFragment.style, spanStart, 942d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang mHeader.sendersDisplayText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 9436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 944b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira return totalWidth; 9456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira /** 9486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * If the subject contains the tag of a mailing-list (text surrounded with 9496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * []), return the subject with that tag ellipsized, e.g. 9506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * "[android-gmail-team] Hello" -> "[andr...] Hello" 9516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira */ 9526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private String filterTag(String subject) { 9536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira String result = subject; 9546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira String formatString = getContext().getResources().getString(R.string.filtered_tag); 9556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (!TextUtils.isEmpty(subject) && subject.charAt(0) == '[') { 9566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int end = subject.indexOf(']'); 9576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (end > 0) { 9586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira String tag = subject.substring(1, end); 9596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira result = String.format(formatString, Utils.ellipsize(tag, 7), 9606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira subject.substring(end + 1)); 9616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return result; 9646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 9676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira protected void onDraw(Canvas canvas) { 9686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Check mark. 9696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.checkboxVisible) { 970c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira Bitmap checkmark = mChecked ? CHECKMARK_ON : CHECKMARK_OFF; 9716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawBitmap(checkmark, mCoordinates.checkmarkX, mCoordinates.checkmarkY, sPaint); 9726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Personal Level. 9753cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira if (mCoordinates.showPersonalLevel && mHeader.personalLevelBitmap != null) { 9766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawBitmap(mHeader.personalLevelBitmap, mCoordinates.personalLevelX, 9776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mCoordinates.personalLevelY, sPaint); 9786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Senders. 9818d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank boolean isUnread = mHeader.unread; 982ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira // Old style senders; apply text colors/ sizes/ styling. 983850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp canvas.save(); 984850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp if (mHeader.sendersDisplayLayout != null) { 985ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setTextSize(mCoordinates.sendersFontSize); 98677d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira sPaint.setTypeface(SendersView.getTypeface(isUnread)); 987850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp sPaint.setColor(getFontColor(isUnread ? sSendersTextColorUnread 988850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp : sSendersTextColorRead)); 989850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp canvas.translate(mCoordinates.sendersX, 990850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mCoordinates.sendersY + mHeader.sendersDisplayLayout.getTopPadding()); 991850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mHeader.sendersDisplayLayout.draw(canvas); 992ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp } else { 993850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp canvas.translate(mCoordinates.sendersX, 994850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mCoordinates.sendersY + sSendersTextViewTopPadding); 995850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mHeader.sendersTextView.layout(0, 0, mSendersWidth, sSendersTextViewHeight); 996850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mHeader.sendersTextView.draw(canvas); 997ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira } 998d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang canvas.restore(); 9996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1000850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp 10016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Subject. 10026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTextSize(mCoordinates.subjectFontSize); 10036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 10046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.save(); 10050b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira if (isActivated() && showActivatedText()) { 10060b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira if (mHeader.subjectLayoutActivated != null) { 10070b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira canvas.translate(mCoordinates.subjectX, mCoordinates.subjectY 10080b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira + mHeader.subjectLayoutActivated.getTopPadding()); 10090b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira mHeader.subjectLayoutActivated.draw(canvas); 10100b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 10110b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } else if (mHeader.subjectLayout != null) { 10124f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira canvas.translate(mCoordinates.subjectX, 10134f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira mCoordinates.subjectY + mHeader.subjectLayout.getTopPadding()); 10144f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira mHeader.subjectLayout.draw(canvas); 10154f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira } 10166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.restore(); 10176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1018b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Folders. 1019b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mCoordinates.showFolders) { 1020b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira mHeader.folderDisplayer.drawFolders(canvas, mCoordinates, mFoldersXEnd, mMode); 1021b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 1022b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 102392939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank // If this folder has a color (combined view/Email), show it here 102492939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank if (mHeader.conversation.color != 0) { 102592939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank sFoldersPaint.setColor(mHeader.conversation.color); 102692939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank sFoldersPaint.setStyle(Paint.Style.FILL); 102792939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank int width = ConversationItemViewCoordinates.getColorBlockWidth(mContext); 102892939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank int height = ConversationItemViewCoordinates.getColorBlockHeight(mContext); 102992939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank canvas.drawRect(mCoordinates.dateXEnd - width, 0, mCoordinates.dateXEnd, 103092939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank height, sFoldersPaint); 103192939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank } 103292939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank 10336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Date background: shown when there is an attachment or a visible 103430fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira // folder. 10356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (!isActivated() 1036280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira && (mHeader.conversation.hasAttachments || 1037280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira (mHeader.folderDisplayer != null 1038280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira && mHeader.folderDisplayer.hasVisibleFolders())) 10390944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira && ConversationItemViewCoordinates.showAttachmentBackground(mMode)) { 1040732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang int leftOffset = (mHeader.conversation.hasAttachments ? mPaperclipX : mDateX) 1041ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira - sDateBackgroundPaddingLeft; 104247ccb45dff1329d5ddac33fb71674048f8c7f51aMindy Pereira int top = mCoordinates.showFolders ? mCoordinates.foldersY : mCoordinates.dateY; 1043bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira mHeader.dateBackground = getDateBackground(mHeader.conversation.hasAttachments); 1044bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira canvas.drawBitmap(mHeader.dateBackground, leftOffset, top, sPaint); 10456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 10466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.dateBackground = null; 10476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 10486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 104954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira // Draw the reply state. Draw nothing if neither replied nor forwarded. 105054467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira if (mCoordinates.showReplyState) { 105154467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira if (mHeader.hasBeenRepliedTo && mHeader.hasBeenForwarded) { 105254467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_REPLIED_AND_FORWARDED, mCoordinates.replyStateX, 105354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 105454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } else if (mHeader.hasBeenRepliedTo) { 105554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_REPLIED, mCoordinates.replyStateX, 105654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 105754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } else if (mHeader.hasBeenForwarded) { 105854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_FORWARDED, mCoordinates.replyStateX, 105954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 10608d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira } else if (mHeader.isInvite) { 1061d5ac9c16e8955abe8366fd1185b86d8bd7c5ac60Mindy Pereira canvas.drawBitmap(STATE_CALENDAR_INVITE, mCoordinates.replyStateX, 10628d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira mCoordinates.replyStateY, null); 106354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } 106454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } 106554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira 10666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Date. 10676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTextSize(mCoordinates.dateFontSize); 10686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 1069ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setColor(sDateTextColor); 10706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira drawText(canvas, mHeader.dateText, mDateX, mCoordinates.dateY - mCoordinates.dateAscent, 10716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint); 10726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 10736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Paper clip icon. 10746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.paperclip != null) { 10756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawBitmap(mHeader.paperclip, mPaperclipX, mCoordinates.paperclipY, sPaint); 10766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 10776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 10786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (mHeader.faded) { 10796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int fadedColor = -1; 10806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sFadedActivatedColor == -1) { 10816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sFadedActivatedColor = mContext.getResources().getColor( 10826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira R.color.faded_activated_conversation_header); 10836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 10846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira fadedColor = sFadedActivatedColor; 10856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int restoreState = canvas.save(); 10866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Rect bounds = canvas.getClipBounds(); 10876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.clipRect(bounds.left, bounds.top, bounds.right 10886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira - mContext.getResources().getDimensionPixelSize(R.dimen.triangle_width), 10896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira bounds.bottom); 10906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawARGB(Color.alpha(fadedColor), Color.red(fadedColor), 10916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Color.green(fadedColor), Color.blue(fadedColor)); 10926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.restoreToCount(restoreState); 10936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 10946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 10956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Star. 10964f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira canvas.drawBitmap(getStarBitmap(), mCoordinates.starX, mCoordinates.starY, sPaint); 10974f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira } 10984f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira 10994f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira private Bitmap getStarBitmap() { 11004f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira return mHeader.conversation.starred ? STAR_ON : STAR_OFF; 11016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1103bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira private Bitmap getDateBackground(boolean hasAttachments) { 1104ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira int leftOffset = (hasAttachments ? mPaperclipX : mDateX) - sDateBackgroundPaddingLeft; 1105bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira if (hasAttachments) { 1106bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira if (sDateBackgroundAttachment == null) { 1107bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira sDateBackgroundAttachment = Bitmap.createScaledBitmap(DATE_BACKGROUND, mViewWidth 1108bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira - leftOffset, sDateBackgroundHeight, false); 1109bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } 1110bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira return sDateBackgroundAttachment; 1111bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } else { 1112bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira if (sDateBackgroundNoAttachment == null) { 1113bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira sDateBackgroundNoAttachment = Bitmap.createScaledBitmap(DATE_BACKGROUND, mViewWidth 1114bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira - leftOffset, sDateBackgroundHeight, false); 1115bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } 1116bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira return sDateBackgroundNoAttachment; 1117bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } 1118bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } 1119bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira 11206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void drawText(Canvas canvas, CharSequence s, int x, int y, TextPaint paint) { 11216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawText(s, 0, s.length(), x, y, paint); 11226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 11246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void updateBackground(boolean isUnread) { 11255c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira if (mBackgroundOverride != -1) { 1126d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira // If the item is animating, we use a color to avoid shrinking a 9-patch 1127d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira // and getting weird artifacts from the overlap. 11285c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setBackgroundColor(mBackgroundOverride); 1129d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira return; 1130d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira } 11310d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal final boolean isListOnTablet = mTabletDevice && mActivity.getViewMode().isListMode(); 11326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (isUnread) { 11330d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal if (isListOnTablet) { 11349d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira if (mChecked) { 11359d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.list_conversation_wide_unread_selected_holo); 11369d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } else { 11379d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.conversation_wide_unread_selector); 11389d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 11409d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira if (mChecked) { 11419d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setCheckedActivatedBackground(); 11429d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } else { 11439d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.conversation_unread_selector); 11449d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 11470d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal if (isListOnTablet) { 11489d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira if (mChecked) { 11499d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.list_conversation_wide_read_selected_holo); 11509d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } else { 11519d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.conversation_wide_read_selector); 11529d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 11549d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira if (mChecked) { 11559d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setCheckedActivatedBackground(); 11569d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } else { 11579d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.conversation_read_selector); 11589d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 1162c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 11639d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira private void setCheckedActivatedBackground() { 1164fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal if (isActivated() && mTabletDevice) { 11659d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.list_arrow_selected_holo); 11669d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } else { 11679d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira setBackgroundResource(R.drawable.list_selected_holo); 11689d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11699d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira } 11709d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira 1171c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira /** 1172c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira * Toggle the check mark on this view and update the conversation 1173c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira */ 1174c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira public void toggleCheckMark() { 1175b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira if (mHeader != null && mHeader.conversation != null) { 1176b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira mChecked = !mChecked; 1177b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira Conversation conv = mHeader.conversation; 1178b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira // Set the list position of this item in the conversation 11791ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira ListView listView = getListView(); 1180b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira conv.position = mChecked && listView != null ? listView.getPositionForView(this) 1181b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira : Conversation.NO_POSITION; 1182b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira if (mSelectedConversationSet != null) { 1183b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira mSelectedConversationSet.toggle(this, conv); 1184b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira } 1185bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // We update the background after the checked state has changed now 1186bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // that 1187bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // we have a selected background asset. Setting the background 1188bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // usually 1189b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira // waits for a layout pass, but we don't need a full layout, just an 1190b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira // update to the background. 1191b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira requestLayout(); 1192d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal } 1193c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1194c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1195c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira /** 1196866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Return if the checkbox for this item is checked. 1197866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1198866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public boolean isChecked() { 1199866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return mChecked; 1200866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1201866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1202866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 1203c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira * Toggle the star on this view and update the conversation. 1204c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira */ 1205866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public void toggleStar() { 12064f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira mHeader.conversation.starred = !mHeader.conversation.starred; 12074f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira Bitmap starBitmap = getStarBitmap(); 1208c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira postInvalidate(mCoordinates.starX, mCoordinates.starY, mCoordinates.starX 12094f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira + starBitmap.getWidth(), 12104f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira mCoordinates.starY + starBitmap.getHeight()); 1211bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook ConversationCursor cursor = (ConversationCursor)mAdapter.getCursor(); 1212bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook cursor.updateBoolean(mContext, mHeader.conversation, ConversationColumns.STARRED, 12134f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira mHeader.conversation.starred); 1214c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1215c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1216866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private boolean isTouchInCheckmark(float x, float y) { 1217c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Everything before senders and include a touch slop. 1218ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira return mHeader.checkboxVisible && x < mCoordinates.sendersX + sTouchSlop; 1219c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1220c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1221866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private boolean isTouchInStar(float x, float y) { 1222c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Everything after the star and include a touch slop. 1223ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira return x > mCoordinates.starX - sTouchSlop; 1224c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1225c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1226304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blank @Override 1227a538984fcc19e7624f2650b119ede39bf1f35846mindyp public boolean canChildBeDismissed() { 1228a538984fcc19e7624f2650b119ede39bf1f35846mindyp return true; 1229a538984fcc19e7624f2650b119ede39bf1f35846mindyp } 1230a538984fcc19e7624f2650b119ede39bf1f35846mindyp 1231a538984fcc19e7624f2650b119ede39bf1f35846mindyp @Override 1232a538984fcc19e7624f2650b119ede39bf1f35846mindyp public void dismiss() { 12335254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp SwipeableListView listView = this.getListView(); 12345254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (listView != null) { 12355254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp getListView().dismissChild(this); 12365254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 12375bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira } 12385bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira 1239b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira /** 1240866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * ConversationItemView is given the first chance to handle touch events. 1241866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1242c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira @Override 1243c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira public boolean onTouchEvent(MotionEvent event) { 12441e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira int x = (int) event.getX(); 12451e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira int y = (int) event.getY(); 1246f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira if (!mSwipeEnabled) { 1247f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira return onTouchEventNoSwipe(event); 1248f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1249c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira switch (event.getAction()) { 1250c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira case MotionEvent.ACTION_DOWN: 1251960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira if (isTouchInCheckmark(x, y) || isTouchInStar(x, y)) { 1252960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira mDownEvent = true; 1253960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1254960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1255c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira break; 1256c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira case MotionEvent.ACTION_UP: 1257c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira if (mDownEvent) { 1258866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira if (isTouchInCheckmark(x, y)) { 1259c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Touch on the check mark 1260960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira mDownEvent = false; 1261c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira toggleCheckMark(); 1262960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1263866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } else if (isTouchInStar(x, y)) { 1264c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Touch on the star 1265960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira mDownEvent = false; 1266c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira toggleStar(); 1267960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1268c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1269c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1270c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira break; 1271c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1272ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal // Let View try to handle it as well. 1273960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira boolean handled = super.onTouchEvent(event); 1274960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira if (event.getAction() == MotionEvent.ACTION_DOWN) { 1275960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1276960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1277960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return handled; 1278c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1279866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1280960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira @Override 1281960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira public boolean performClick() { 1282960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira boolean handled = super.performClick(); 1283960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira ListView list = getListView(); 1284960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira if (list != null) { 1285960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira int pos = list.getPositionForView(this); 1286960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira list.performItemClick(this, pos, mHeader.conversation.id); 1287960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1288960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return handled; 12891e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira } 12901e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira 1291a538984fcc19e7624f2650b119ede39bf1f35846mindyp private SwipeableListView getListView() { 12925254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp SwipeableListView v = (SwipeableListView) ((SwipeableConversationItemView) getParent()) 12935254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp .getListView(); 12945254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (v == null) { 12955254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp v = mAdapter.getListView(); 12965254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 12975254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp return v; 12981ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira } 12991ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira 1300f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira private boolean onTouchEventNoSwipe(MotionEvent event) { 1301f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira boolean handled = true; 1302f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira 1303f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira int x = (int) event.getX(); 1304f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira int y = (int) event.getY(); 1305f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira switch (event.getAction()) { 1306f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira case MotionEvent.ACTION_DOWN: 1307f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira mDownEvent = true; 1308f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // In order to allow the down event and subsequent move events 1309f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // to bubble to the swipe handler, we need to return that all 1310f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // down events are handled. 1311f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira handled = isTouchInCheckmark(x, y) || isTouchInStar(x, y); 1312f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira break; 1313f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira case MotionEvent.ACTION_CANCEL: 1314f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira mDownEvent = false; 1315f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira break; 1316f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira case MotionEvent.ACTION_UP: 1317f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira if (mDownEvent) { 1318f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // ConversationItemView gets the first chance to handle up 1319f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // events if there was a down event and there was no move 1320f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // event in between. In this case, ConversationItemView 1321f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // received the down event, and then an up event in the 1322f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // same location (+/- slop). Treat this as a click on the 1323f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // view or on a specific part of the view. 1324f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira if (isTouchInCheckmark(x, y)) { 1325f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // Touch on the check mark 1326f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira toggleCheckMark(); 1327f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } else if (isTouchInStar(x, y)) { 1328f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // Touch on the star 1329f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira toggleStar(); 1330f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1331f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira handled = true; 1332f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } else { 1333f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // There was no down event that this view was made aware of, 1334f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira // therefore it cannot handle it. 1335f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira handled = false; 1336f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1337f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira break; 1338f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1339f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira 1340ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal // Let View try to handle it as well. 1341ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal return handled || super.onTouchEvent(event); 1342f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1343f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira 1344866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 13455c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira * Reset any state associated with this conversation item view so that it 13465c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira * can be reused. 13475c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira */ 13485c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira public void reset() { 13495c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira mBackgroundOverride = -1; 13505c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setAlpha(1); 13515c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setTranslationX(0); 13525c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setAnimatedHeight(-1); 13535c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira } 13545c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira 13555c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira /** 1356866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1357866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * back from a destructive action. 1358866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * @param listener 1359866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1360bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void startSwipeUndoAnimation(ViewMode viewMode, final AnimatorListener listener) { 1361067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator undoAnimator = createTranslateXAnimation(true); 13626c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira undoAnimator.addListener(listener); 1363350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira undoAnimator.start(); 1364866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1365866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1366bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira /** 1367bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1368bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira * back from a destructive action. 1369bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira * @param listener 1370bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira */ 1371bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void startUndoAnimation(ViewMode viewMode, final AnimatorListener listener) { 1372bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira int minHeight = ConversationItemViewCoordinates.getMinHeight(mContext, viewMode); 1373bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira setMinimumHeight(minHeight); 1374067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira mAnimatedHeight = 0; 1375067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator height = createHeightAnimation(true); 1376067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira Animator fade = ObjectAnimator.ofFloat(this, "itemAlpha", 0, 1.0f); 1377067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira fade.setDuration(sShrinkAnimationDuration); 1378067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira fade.setInterpolator(new DecelerateInterpolator(2.0f)); 1379067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira AnimatorSet transitionSet = new AnimatorSet(); 1380067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.playTogether(height, fade); 1381067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.addListener(listener); 1382067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.start(); 1383067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1384067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 1385067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira /** 1386067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1387067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * back from a destructive action. 1388067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * @param listener 1389067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira */ 1390067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira public void startDestroyWithSwipeAnimation(final AnimatorListener listener) { 1391067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator slide = createTranslateXAnimation(false); 1392067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator height = createHeightAnimation(false); 1393bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira AnimatorSet transitionSet = new AnimatorSet(); 1394067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.playSequentially(slide, height); 1395067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.addListener(listener); 1396bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira transitionSet.start(); 1397bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1398bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 1399067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private ObjectAnimator createTranslateXAnimation(boolean show) { 1400067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final float start = show ? sUndoAnimationOffset : 0f; 1401067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final float end = show ? 0f : sUndoAnimationOffset; 1402067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator slide = ObjectAnimator.ofFloat(this, "translationX", start, end); 1403067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira slide.setInterpolator(new DecelerateInterpolator(2.0f)); 1404067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira slide.setDuration(sSlideAnimationDuration); 1405067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return slide; 1406067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1407067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 14085c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira public void startDestroyAnimation(final AnimatorListener listener) { 14095c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira ObjectAnimator height = createHeightAnimation(false); 14105c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira int minHeight = ConversationItemViewCoordinates.getMinHeight(mContext, 14115c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira mActivity.getViewMode()); 14125c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setMinimumHeight(0); 14135c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira mBackgroundOverride = sAnimatingBackgroundColor; 14145c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira setBackgroundColor(mBackgroundOverride); 14155c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira mAnimatedHeight = minHeight; 14165c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira height.addListener(listener); 14175c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira height.start(); 14185c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira } 14195c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira 1420067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private ObjectAnimator createHeightAnimation(boolean show) { 1421067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira int minHeight = ConversationItemViewCoordinates.getMinHeight(getContext(), 1422067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira mActivity.getViewMode()); 1423067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final int start = show ? 0 : minHeight; 1424067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira final int end = show ? minHeight : 0; 1425067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator height = ObjectAnimator.ofInt(this, "animatedHeight", start, end); 1426067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira height.setInterpolator(new DecelerateInterpolator(2.0f)); 1427067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira height.setDuration(sShrinkAnimationDuration); 1428067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return height; 1429067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1430067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 1431bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira // Used by animator 1432bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira @SuppressWarnings("unused") 1433bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void setItemAlpha(float alpha) { 1434bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira setAlpha(alpha); 1435bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira invalidate(); 1436bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1437bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 1438bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira // Used by animator 1439bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira @SuppressWarnings("unused") 1440bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira public void setAnimatedHeight(int height) { 1441bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira mAnimatedHeight = height; 1442bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira requestLayout(); 1443bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1444bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 1445350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira @Override 1446350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1447bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira if (mAnimatedHeight == -1) { 1448bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira int height = measureHeight(heightMeasureSpec, 1449e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira ConversationItemViewCoordinates.getMode(mContext, mActivity.getViewMode())); 1450bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira setMeasuredDimension(widthMeasureSpec, height); 1451bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } else { 1452bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mAnimatedHeight); 1453bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1454866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1455866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1456350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira /** 1457350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira * Determine the height of this view. 1458350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira * @param measureSpec A measureSpec packed into an int 1459350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira * @param mode The current mode of this view 1460350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira * @return The height of the view, honoring constraints from measureSpec 1461350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira */ 1462350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira private int measureHeight(int measureSpec, int mode) { 1463350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira int result = 0; 1464350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira int specMode = MeasureSpec.getMode(measureSpec); 1465350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira int specSize = MeasureSpec.getSize(measureSpec); 1466350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira 1467350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira if (specMode == MeasureSpec.EXACTLY) { 1468350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira // We were told how big to be 1469350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira result = specSize; 1470350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira } else { 1471350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira // Measure the text 1472350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira result = ConversationItemViewCoordinates.getHeight(mContext, mode); 1473350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira if (specMode == MeasureSpec.AT_MOST) { 1474350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira // Respect AT_MOST value if that was what is called for by 1475350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira // measureSpec 1476350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira result = Math.min(result, specSize); 1477350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira } 1478350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira } 1479350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira return result; 1480866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1481866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1482866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 1483866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Get the current position of this conversation item in the list. 1484866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1485866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public int getPosition() { 1486866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira return mHeader != null && mHeader.conversation != null ? 1487866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira mHeader.conversation.position : -1; 1488866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1489acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira 14906c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira @Override 1491a538984fcc19e7624f2650b119ede39bf1f35846mindyp public View getSwipeableView() { 14926c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira return this; 14936c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 1494bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook} 1495