Loading core/java/com/android/internal/widget/ConversationLayout.java +59 −14 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.internal.widget; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -35,6 +38,7 @@ import android.os.Bundle; import android.os.Parcelable; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.Gravity; Loading @@ -46,6 +50,7 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.TextView; Loading Loading @@ -109,13 +114,13 @@ public class ConversationLayout extends FrameLayout private View mExpandButtonContainer; private ViewGroup mExpandButtonAndContentContainer; private NotificationExpandButton mExpandButton; private MessagingLinearLayout mImageMessageContainer; private int mExpandButtonExpandedTopMargin; private int mBadgedSideMargins; private int mIconSizeBadged; private int mIconSizeCentered; private CachingIconView mIcon; private int mExpandedGroupTopMargin; private int mExpandButtonExpandedSize; private View mConversationFacePile; private int mNotificationBackgroundColor; private CharSequence mFallbackChatName; Loading @@ -126,6 +131,7 @@ public class ConversationLayout extends FrameLayout private View mContentContainer; private boolean mExpandable = true; private int mContentMarginEnd; private Rect mMessagingClipRect; public ConversationLayout(@NonNull Context context) { super(context); Loading @@ -150,12 +156,13 @@ public class ConversationLayout extends FrameLayout super.onFinishInflate(); mMessagingLinearLayout = findViewById(R.id.notification_messaging); mMessagingLinearLayout.setMessagingLayout(this); mImageMessageContainer = findViewById(R.id.conversation_image_message_container); // We still want to clip, but only on the top, since views can temporarily out of bounds // during transitions. DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int size = Math.max(displayMetrics.widthPixels, displayMetrics.heightPixels); Rect rect = new Rect(0, 0, size, size); mMessagingLinearLayout.setClipBounds(rect); mMessagingClipRect = new Rect(0, 0, size, size); setMessagingClippingDisabled(false); mTitleView = findViewById(R.id.title); mAvatarSize = getResources().getDimensionPixelSize(R.dimen.messaging_avatar_size); mTextPaint.setTextAlign(Paint.Align.CENTER); Loading @@ -176,8 +183,6 @@ public class ConversationLayout extends FrameLayout mExpandButton = findViewById(R.id.expand_button); mExpandButtonExpandedTopMargin = getResources().getDimensionPixelSize( R.dimen.conversation_expand_button_top_margin_expanded); mExpandButtonExpandedSize = getResources().getDimensionPixelSize( R.dimen.conversation_expand_button_expanded_size); mNotificationHeaderExpandedPadding = getResources().getDimensionPixelSize( R.dimen.conversation_header_expanded_padding_end); mContentMarginEnd = getResources().getDimensionPixelSize( Loading Loading @@ -370,6 +375,41 @@ public class ConversationLayout extends FrameLayout messagingGroup.setCanHideSenderIfFirst(canHide); } updateIconPositionAndSize(); updateImageMessages(); } private void updateImageMessages() { boolean displayExternalImage = false; ArraySet<View> newMessages = new ArraySet<>(); if (mIsCollapsed) { // When collapsed, we're displaying all image messages in a dedicated container // on the right of the layout instead of inline. Let's add all isolated images there int imageIndex = 0; for (int i = 0; i < mGroups.size(); i++) { MessagingGroup messagingGroup = mGroups.get(i); MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage(); if (isolatedMessage != null) { newMessages.add(isolatedMessage.getView()); displayExternalImage = true; if (imageIndex != mImageMessageContainer.indexOfChild(isolatedMessage.getView())) { mImageMessageContainer.removeView(isolatedMessage.getView()); mImageMessageContainer.addView(isolatedMessage.getView(), imageIndex); } imageIndex++; } } } // Remove all messages that don't belong into the image layout for (int i = 0; i < mImageMessageContainer.getChildCount(); i++) { View child = mImageMessageContainer.getChildAt(i); if (!newMessages.contains(child)) { mImageMessageContainer.removeView(child); i--; } } mImageMessageContainer.setVisibility(displayExternalImage ? VISIBLE : GONE); } private void bindFacePile() { Loading Loading @@ -662,7 +702,9 @@ public class ConversationLayout extends FrameLayout newGroup = MessagingGroup.createGroup(mMessagingLinearLayout); mAddedGroups.add(newGroup); } newGroup.setDisplayImagesAtEnd(mIsCollapsed); newGroup.setImageDisplayLocation(mIsCollapsed ? IMAGE_DISPLAY_LOCATION_EXTERNAL : IMAGE_DISPLAY_LOCATION_INLINE); newGroup.setIsInConversation(true); newGroup.setLayoutColor(mLayoutColor); newGroup.setTextColors(mSenderTextColor, mMessageTextColor); Loading Loading @@ -817,6 +859,10 @@ public class ConversationLayout extends FrameLayout return mMessagingLinearLayout; } public @NonNull ViewGroup getImageMessageContainer() { return mImageMessageContainer; } public ArrayList<MessagingGroup> getMessagingGroups() { return mGroups; } Loading @@ -827,20 +873,17 @@ public class ConversationLayout extends FrameLayout int gravity; int topMargin = 0; ViewGroup newContainer; int newContainerHeight; if (mIsCollapsed) { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; gravity = Gravity.CENTER; newContainer = mExpandButtonAndContentContainer; newContainerHeight = LayoutParams.MATCH_PARENT; } else { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; topMargin = mExpandButtonExpandedTopMargin; newContainer = this; newContainerHeight = mExpandButtonExpandedSize; } mExpandButton.setImageDrawable(getContext().getDrawable(drawableId)); mExpandButton.setColorFilter(mExpandButton.getOriginalNotificationColor()); Loading @@ -850,14 +893,11 @@ public class ConversationLayout extends FrameLayout if (newContainer != mExpandButtonContainer.getParent()) { ((ViewGroup) mExpandButtonContainer.getParent()).removeView(mExpandButtonContainer); newContainer.addView(mExpandButtonContainer); MarginLayoutParams layoutParams = (MarginLayoutParams) mExpandButtonContainer.getLayoutParams(); layoutParams.height = newContainerHeight; mExpandButtonContainer.setLayoutParams(layoutParams); } // update if the expand button is centered FrameLayout.LayoutParams layoutParams = (LayoutParams) mExpandButton.getLayoutParams(); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mExpandButton.getLayoutParams(); layoutParams.gravity = gravity; layoutParams.topMargin = topMargin; mExpandButton.setLayoutParams(layoutParams); Loading Loading @@ -905,4 +945,9 @@ public class ConversationLayout extends FrameLayout } updateContentPaddings(); } @Override public void setMessagingClippingDisabled(boolean clippingDisabled) { mMessagingLinearLayout.setClipBounds(clippingDisabled ? null : mMessagingClipRect); } } core/java/com/android/internal/widget/IMessagingLayout.java +5 −0 Original line number Diff line number Diff line Loading @@ -39,4 +39,9 @@ public interface IMessagingLayout { * @return the list of messaging groups */ ArrayList<MessagingGroup> getMessagingGroups(); /** * Disable the clipping of the messaging container. */ void setMessagingClippingDisabled(boolean clippingDisabled); } core/java/com/android/internal/widget/MessagingGroup.java +40 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.annotation.AttrRes; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; Loading Loading @@ -44,6 +45,8 @@ import android.widget.RemoteViews; import com.android.internal.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; Loading @@ -54,6 +57,23 @@ import java.util.List; public class MessagingGroup extends LinearLayout implements MessagingLinearLayout.MessagingChild { private static Pools.SimplePool<MessagingGroup> sInstancePool = new Pools.SynchronizedPool<>(10); /** * Images are displayed inline. */ public static final int IMAGE_DISPLAY_LOCATION_INLINE = 0; /** * Images are displayed at the end of the group. */ public static final int IMAGE_DISPLAY_LOCATION_AT_END = 1; /** * Images are displayed externally. */ public static final int IMAGE_DISPLAY_LOCATION_EXTERNAL = 2; private MessagingLinearLayout mMessageContainer; ImageFloatingTextView mSenderView; private ImageView mAvatarView; Loading @@ -70,7 +90,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou private boolean mIsHidingAnimated; private boolean mNeedsGeneratedAvatar; private Person mSender; private boolean mImagesAtEnd; private @ImageDisplayLocation int mImageDisplayLocation; private ViewGroup mImageContainer; private MessagingImageMessage mIsolatedMessage; private boolean mClippingDisabled; Loading Loading @@ -476,7 +496,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mAddedMessages.add(message); } boolean isImage = message instanceof MessagingImageMessage; if (mImagesAtEnd && isImage) { if (mImageDisplayLocation != IMAGE_DISPLAY_LOCATION_INLINE && isImage) { isolatedMessage = (MessagingImageMessage) message; } else { if (removeFromParentIfDifferent(message, mMessageContainer)) { Loading @@ -500,9 +520,12 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou } } if (isolatedMessage != null) { if (removeFromParentIfDifferent(isolatedMessage, mImageContainer)) { if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END && removeFromParentIfDifferent(isolatedMessage, mImageContainer)) { mImageContainer.removeAllViews(); mImageContainer.addView(isolatedMessage.getView()); } else if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_EXTERNAL) { mImageContainer.removeAllViews(); } isolatedMessage.setIsolated(true); } else if (mIsolatedMessage != null) { Loading @@ -515,7 +538,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou } private void updateImageContainerVisibility() { mImageContainer.setVisibility(mIsolatedMessage != null && mImagesAtEnd mImageContainer.setVisibility(mIsolatedMessage != null && mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END ? View.VISIBLE : View.GONE); } Loading Loading @@ -620,9 +644,9 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mClippingDisabled = disabled; } public void setDisplayImagesAtEnd(boolean atEnd) { if (mImagesAtEnd != atEnd) { mImagesAtEnd = atEnd; public void setImageDisplayLocation(@ImageDisplayLocation int displayLocation) { if (mImageDisplayLocation != displayLocation) { mImageDisplayLocation = displayLocation; updateImageContainerVisibility(); } } Loading Loading @@ -670,4 +694,13 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mMessagingIconContainer.setLayoutParams(layoutParams); } } @IntDef(prefix = {"IMAGE_DISPLAY_LOCATION_"}, value = { IMAGE_DISPLAY_LOCATION_INLINE, IMAGE_DISPLAY_LOCATION_AT_END, IMAGE_DISPLAY_LOCATION_EXTERNAL }) @Retention(RetentionPolicy.SOURCE) private @interface ImageDisplayLocation { } } core/java/com/android/internal/widget/MessagingImageMessage.java +19 −11 Original line number Diff line number Diff line Loading @@ -149,10 +149,16 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onDraw(Canvas canvas) { canvas.save(); canvas.clipPath(getRoundedRectPath()); int width = (int) Math.max(getActualWidth(), getActualHeight() * mAspectRatio); int height = (int) (width / mAspectRatio); // Calculate the right sizing ensuring that the image is nicely centered in the layout // during transitions int width = (int) Math.max((Math.min(getHeight(), getActualHeight()) * mAspectRatio), getActualWidth()); int height = (int) Math.max((Math.min(getWidth(), getActualWidth()) / mAspectRatio), getActualHeight()); height = (int) Math.max(height, width / mAspectRatio); int left = (int) ((getActualWidth() - width) / 2.0f); mDrawable.setBounds(left, 0, left + width, height); int top = (int) ((getActualHeight() - height) / 2.0f); mDrawable.setBounds(left, top, left + width, top + height); mDrawable.draw(canvas); canvas.restore(); } Loading Loading @@ -222,8 +228,17 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mIsIsolated) { // When isolated we have a fixed size, let's use that sizing. setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); } else { // If we are displaying inline, we never want to go wider than actual size of the // image, otherwise it will look quite blurry. int width = Math.min(MeasureSpec.getSize(widthMeasureSpec), mDrawable.getIntrinsicWidth()); int height = (int) Math.min(MeasureSpec.getSize(heightMeasureSpec), width / mAspectRatio); setMeasuredDimension(width, height); } } Loading @@ -231,7 +246,7 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // TODO: ensure that this isn't called when transforming setActualWidth(getStaticWidth()); setActualWidth(getWidth()); setActualHeight(getHeight()); } Loading @@ -258,13 +273,6 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage return mActualHeight; } public int getStaticWidth() { if (mIsIsolated) { return getWidth(); } return (int) (getHeight() * mAspectRatio); } public void setIsolated(boolean isolated) { if (mIsIsolated != isolated) { mIsIsolated = isolated; Loading core/java/com/android/internal/widget/MessagingLayout.java +11 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.internal.widget; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_AT_END; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -447,7 +450,9 @@ public class MessagingLayout extends FrameLayout newGroup = MessagingGroup.createGroup(mMessagingLinearLayout); mAddedGroups.add(newGroup); } newGroup.setDisplayImagesAtEnd(mDisplayImagesAtEnd); newGroup.setImageDisplayLocation(mDisplayImagesAtEnd ? IMAGE_DISPLAY_LOCATION_AT_END : IMAGE_DISPLAY_LOCATION_INLINE); newGroup.setIsInConversation(false); newGroup.setLayoutColor(mLayoutColor); newGroup.setTextColors(mSenderTextColor, mMessageTextColor); Loading Loading @@ -599,4 +604,9 @@ public class MessagingLayout extends FrameLayout public ArrayList<MessagingGroup> getMessagingGroups() { return mGroups; } @Override public void setMessagingClippingDisabled(boolean clippingDisabled) { // Don't do anything, this is only used for the ConversationLayout } } Loading
core/java/com/android/internal/widget/ConversationLayout.java +59 −14 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.internal.widget; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -35,6 +38,7 @@ import android.os.Bundle; import android.os.Parcelable; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.Gravity; Loading @@ -46,6 +50,7 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.TextView; Loading Loading @@ -109,13 +114,13 @@ public class ConversationLayout extends FrameLayout private View mExpandButtonContainer; private ViewGroup mExpandButtonAndContentContainer; private NotificationExpandButton mExpandButton; private MessagingLinearLayout mImageMessageContainer; private int mExpandButtonExpandedTopMargin; private int mBadgedSideMargins; private int mIconSizeBadged; private int mIconSizeCentered; private CachingIconView mIcon; private int mExpandedGroupTopMargin; private int mExpandButtonExpandedSize; private View mConversationFacePile; private int mNotificationBackgroundColor; private CharSequence mFallbackChatName; Loading @@ -126,6 +131,7 @@ public class ConversationLayout extends FrameLayout private View mContentContainer; private boolean mExpandable = true; private int mContentMarginEnd; private Rect mMessagingClipRect; public ConversationLayout(@NonNull Context context) { super(context); Loading @@ -150,12 +156,13 @@ public class ConversationLayout extends FrameLayout super.onFinishInflate(); mMessagingLinearLayout = findViewById(R.id.notification_messaging); mMessagingLinearLayout.setMessagingLayout(this); mImageMessageContainer = findViewById(R.id.conversation_image_message_container); // We still want to clip, but only on the top, since views can temporarily out of bounds // during transitions. DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int size = Math.max(displayMetrics.widthPixels, displayMetrics.heightPixels); Rect rect = new Rect(0, 0, size, size); mMessagingLinearLayout.setClipBounds(rect); mMessagingClipRect = new Rect(0, 0, size, size); setMessagingClippingDisabled(false); mTitleView = findViewById(R.id.title); mAvatarSize = getResources().getDimensionPixelSize(R.dimen.messaging_avatar_size); mTextPaint.setTextAlign(Paint.Align.CENTER); Loading @@ -176,8 +183,6 @@ public class ConversationLayout extends FrameLayout mExpandButton = findViewById(R.id.expand_button); mExpandButtonExpandedTopMargin = getResources().getDimensionPixelSize( R.dimen.conversation_expand_button_top_margin_expanded); mExpandButtonExpandedSize = getResources().getDimensionPixelSize( R.dimen.conversation_expand_button_expanded_size); mNotificationHeaderExpandedPadding = getResources().getDimensionPixelSize( R.dimen.conversation_header_expanded_padding_end); mContentMarginEnd = getResources().getDimensionPixelSize( Loading Loading @@ -370,6 +375,41 @@ public class ConversationLayout extends FrameLayout messagingGroup.setCanHideSenderIfFirst(canHide); } updateIconPositionAndSize(); updateImageMessages(); } private void updateImageMessages() { boolean displayExternalImage = false; ArraySet<View> newMessages = new ArraySet<>(); if (mIsCollapsed) { // When collapsed, we're displaying all image messages in a dedicated container // on the right of the layout instead of inline. Let's add all isolated images there int imageIndex = 0; for (int i = 0; i < mGroups.size(); i++) { MessagingGroup messagingGroup = mGroups.get(i); MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage(); if (isolatedMessage != null) { newMessages.add(isolatedMessage.getView()); displayExternalImage = true; if (imageIndex != mImageMessageContainer.indexOfChild(isolatedMessage.getView())) { mImageMessageContainer.removeView(isolatedMessage.getView()); mImageMessageContainer.addView(isolatedMessage.getView(), imageIndex); } imageIndex++; } } } // Remove all messages that don't belong into the image layout for (int i = 0; i < mImageMessageContainer.getChildCount(); i++) { View child = mImageMessageContainer.getChildAt(i); if (!newMessages.contains(child)) { mImageMessageContainer.removeView(child); i--; } } mImageMessageContainer.setVisibility(displayExternalImage ? VISIBLE : GONE); } private void bindFacePile() { Loading Loading @@ -662,7 +702,9 @@ public class ConversationLayout extends FrameLayout newGroup = MessagingGroup.createGroup(mMessagingLinearLayout); mAddedGroups.add(newGroup); } newGroup.setDisplayImagesAtEnd(mIsCollapsed); newGroup.setImageDisplayLocation(mIsCollapsed ? IMAGE_DISPLAY_LOCATION_EXTERNAL : IMAGE_DISPLAY_LOCATION_INLINE); newGroup.setIsInConversation(true); newGroup.setLayoutColor(mLayoutColor); newGroup.setTextColors(mSenderTextColor, mMessageTextColor); Loading Loading @@ -817,6 +859,10 @@ public class ConversationLayout extends FrameLayout return mMessagingLinearLayout; } public @NonNull ViewGroup getImageMessageContainer() { return mImageMessageContainer; } public ArrayList<MessagingGroup> getMessagingGroups() { return mGroups; } Loading @@ -827,20 +873,17 @@ public class ConversationLayout extends FrameLayout int gravity; int topMargin = 0; ViewGroup newContainer; int newContainerHeight; if (mIsCollapsed) { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; gravity = Gravity.CENTER; newContainer = mExpandButtonAndContentContainer; newContainerHeight = LayoutParams.MATCH_PARENT; } else { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; topMargin = mExpandButtonExpandedTopMargin; newContainer = this; newContainerHeight = mExpandButtonExpandedSize; } mExpandButton.setImageDrawable(getContext().getDrawable(drawableId)); mExpandButton.setColorFilter(mExpandButton.getOriginalNotificationColor()); Loading @@ -850,14 +893,11 @@ public class ConversationLayout extends FrameLayout if (newContainer != mExpandButtonContainer.getParent()) { ((ViewGroup) mExpandButtonContainer.getParent()).removeView(mExpandButtonContainer); newContainer.addView(mExpandButtonContainer); MarginLayoutParams layoutParams = (MarginLayoutParams) mExpandButtonContainer.getLayoutParams(); layoutParams.height = newContainerHeight; mExpandButtonContainer.setLayoutParams(layoutParams); } // update if the expand button is centered FrameLayout.LayoutParams layoutParams = (LayoutParams) mExpandButton.getLayoutParams(); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mExpandButton.getLayoutParams(); layoutParams.gravity = gravity; layoutParams.topMargin = topMargin; mExpandButton.setLayoutParams(layoutParams); Loading Loading @@ -905,4 +945,9 @@ public class ConversationLayout extends FrameLayout } updateContentPaddings(); } @Override public void setMessagingClippingDisabled(boolean clippingDisabled) { mMessagingLinearLayout.setClipBounds(clippingDisabled ? null : mMessagingClipRect); } }
core/java/com/android/internal/widget/IMessagingLayout.java +5 −0 Original line number Diff line number Diff line Loading @@ -39,4 +39,9 @@ public interface IMessagingLayout { * @return the list of messaging groups */ ArrayList<MessagingGroup> getMessagingGroups(); /** * Disable the clipping of the messaging container. */ void setMessagingClippingDisabled(boolean clippingDisabled); }
core/java/com/android/internal/widget/MessagingGroup.java +40 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.annotation.AttrRes; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; Loading Loading @@ -44,6 +45,8 @@ import android.widget.RemoteViews; import com.android.internal.R; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; Loading @@ -54,6 +57,23 @@ import java.util.List; public class MessagingGroup extends LinearLayout implements MessagingLinearLayout.MessagingChild { private static Pools.SimplePool<MessagingGroup> sInstancePool = new Pools.SynchronizedPool<>(10); /** * Images are displayed inline. */ public static final int IMAGE_DISPLAY_LOCATION_INLINE = 0; /** * Images are displayed at the end of the group. */ public static final int IMAGE_DISPLAY_LOCATION_AT_END = 1; /** * Images are displayed externally. */ public static final int IMAGE_DISPLAY_LOCATION_EXTERNAL = 2; private MessagingLinearLayout mMessageContainer; ImageFloatingTextView mSenderView; private ImageView mAvatarView; Loading @@ -70,7 +90,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou private boolean mIsHidingAnimated; private boolean mNeedsGeneratedAvatar; private Person mSender; private boolean mImagesAtEnd; private @ImageDisplayLocation int mImageDisplayLocation; private ViewGroup mImageContainer; private MessagingImageMessage mIsolatedMessage; private boolean mClippingDisabled; Loading Loading @@ -476,7 +496,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mAddedMessages.add(message); } boolean isImage = message instanceof MessagingImageMessage; if (mImagesAtEnd && isImage) { if (mImageDisplayLocation != IMAGE_DISPLAY_LOCATION_INLINE && isImage) { isolatedMessage = (MessagingImageMessage) message; } else { if (removeFromParentIfDifferent(message, mMessageContainer)) { Loading @@ -500,9 +520,12 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou } } if (isolatedMessage != null) { if (removeFromParentIfDifferent(isolatedMessage, mImageContainer)) { if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END && removeFromParentIfDifferent(isolatedMessage, mImageContainer)) { mImageContainer.removeAllViews(); mImageContainer.addView(isolatedMessage.getView()); } else if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_EXTERNAL) { mImageContainer.removeAllViews(); } isolatedMessage.setIsolated(true); } else if (mIsolatedMessage != null) { Loading @@ -515,7 +538,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou } private void updateImageContainerVisibility() { mImageContainer.setVisibility(mIsolatedMessage != null && mImagesAtEnd mImageContainer.setVisibility(mIsolatedMessage != null && mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END ? View.VISIBLE : View.GONE); } Loading Loading @@ -620,9 +644,9 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mClippingDisabled = disabled; } public void setDisplayImagesAtEnd(boolean atEnd) { if (mImagesAtEnd != atEnd) { mImagesAtEnd = atEnd; public void setImageDisplayLocation(@ImageDisplayLocation int displayLocation) { if (mImageDisplayLocation != displayLocation) { mImageDisplayLocation = displayLocation; updateImageContainerVisibility(); } } Loading Loading @@ -670,4 +694,13 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mMessagingIconContainer.setLayoutParams(layoutParams); } } @IntDef(prefix = {"IMAGE_DISPLAY_LOCATION_"}, value = { IMAGE_DISPLAY_LOCATION_INLINE, IMAGE_DISPLAY_LOCATION_AT_END, IMAGE_DISPLAY_LOCATION_EXTERNAL }) @Retention(RetentionPolicy.SOURCE) private @interface ImageDisplayLocation { } }
core/java/com/android/internal/widget/MessagingImageMessage.java +19 −11 Original line number Diff line number Diff line Loading @@ -149,10 +149,16 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onDraw(Canvas canvas) { canvas.save(); canvas.clipPath(getRoundedRectPath()); int width = (int) Math.max(getActualWidth(), getActualHeight() * mAspectRatio); int height = (int) (width / mAspectRatio); // Calculate the right sizing ensuring that the image is nicely centered in the layout // during transitions int width = (int) Math.max((Math.min(getHeight(), getActualHeight()) * mAspectRatio), getActualWidth()); int height = (int) Math.max((Math.min(getWidth(), getActualWidth()) / mAspectRatio), getActualHeight()); height = (int) Math.max(height, width / mAspectRatio); int left = (int) ((getActualWidth() - width) / 2.0f); mDrawable.setBounds(left, 0, left + width, height); int top = (int) ((getActualHeight() - height) / 2.0f); mDrawable.setBounds(left, top, left + width, top + height); mDrawable.draw(canvas); canvas.restore(); } Loading Loading @@ -222,8 +228,17 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mIsIsolated) { // When isolated we have a fixed size, let's use that sizing. setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); } else { // If we are displaying inline, we never want to go wider than actual size of the // image, otherwise it will look quite blurry. int width = Math.min(MeasureSpec.getSize(widthMeasureSpec), mDrawable.getIntrinsicWidth()); int height = (int) Math.min(MeasureSpec.getSize(heightMeasureSpec), width / mAspectRatio); setMeasuredDimension(width, height); } } Loading @@ -231,7 +246,7 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // TODO: ensure that this isn't called when transforming setActualWidth(getStaticWidth()); setActualWidth(getWidth()); setActualHeight(getHeight()); } Loading @@ -258,13 +273,6 @@ public class MessagingImageMessage extends ImageView implements MessagingMessage return mActualHeight; } public int getStaticWidth() { if (mIsIsolated) { return getWidth(); } return (int) (getHeight() * mAspectRatio); } public void setIsolated(boolean isolated) { if (mIsIsolated != isolated) { mIsIsolated = isolated; Loading
core/java/com/android/internal/widget/MessagingLayout.java +11 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.internal.widget; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_AT_END; import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -447,7 +450,9 @@ public class MessagingLayout extends FrameLayout newGroup = MessagingGroup.createGroup(mMessagingLinearLayout); mAddedGroups.add(newGroup); } newGroup.setDisplayImagesAtEnd(mDisplayImagesAtEnd); newGroup.setImageDisplayLocation(mDisplayImagesAtEnd ? IMAGE_DISPLAY_LOCATION_AT_END : IMAGE_DISPLAY_LOCATION_INLINE); newGroup.setIsInConversation(false); newGroup.setLayoutColor(mLayoutColor); newGroup.setTextColors(mSenderTextColor, mMessageTextColor); Loading Loading @@ -599,4 +604,9 @@ public class MessagingLayout extends FrameLayout public ArrayList<MessagingGroup> getMessagingGroups() { return mGroups; } @Override public void setMessagingClippingDisabled(boolean clippingDisabled) { // Don't do anything, this is only used for the ConversationLayout } }