diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-03-20 22:20:28 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-20 22:20:28 +0000 |
| commit | 4bd7796e1dae8b37d3768bb15283256158c4a11f (patch) | |
| tree | afdf87d269e45a63eb179c38bc63e7aa5ffe8341 /core/java | |
| parent | 100012bd1c3d7b1d5dddfb451d1b74a7e74452c5 (diff) | |
| parent | 514b52c091f95c47c7c53a8206dfe3be08273cd5 (diff) | |
Merge "Made image messages display externally in the layout" into rvc-dev
Diffstat (limited to 'core/java')
5 files changed, 134 insertions, 33 deletions
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 67e592796181..4028fda6c1df 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -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; @@ -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; @@ -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; @@ -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; @@ -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); @@ -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); @@ -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( @@ -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() { @@ -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); @@ -817,6 +859,10 @@ public class ConversationLayout extends FrameLayout return mMessagingLinearLayout; } + public @NonNull ViewGroup getImageMessageContainer() { + return mImageMessageContainer; + } + public ArrayList<MessagingGroup> getMessagingGroups() { return mGroups; } @@ -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()); @@ -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); @@ -905,4 +945,9 @@ public class ConversationLayout extends FrameLayout } updateContentPaddings(); } + + @Override + public void setMessagingClippingDisabled(boolean clippingDisabled) { + mMessagingLinearLayout.setClipBounds(clippingDisabled ? null : mMessagingClipRect); + } } diff --git a/core/java/com/android/internal/widget/IMessagingLayout.java b/core/java/com/android/internal/widget/IMessagingLayout.java index 149d05641a0b..b72c081f134c 100644 --- a/core/java/com/android/internal/widget/IMessagingLayout.java +++ b/core/java/com/android/internal/widget/IMessagingLayout.java @@ -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); } diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index c68da97ab3b4..53272f7eebf9 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -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; @@ -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; @@ -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; @@ -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; @@ -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)) { @@ -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) { @@ -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); } @@ -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(); } } @@ -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 { + } } diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java index c243f3b583e5..27689d4d43f9 100644 --- a/core/java/com/android/internal/widget/MessagingImageMessage.java +++ b/core/java/com/android/internal/widget/MessagingImageMessage.java @@ -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(); } @@ -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); } } @@ -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()); } @@ -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; diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index 3fb5d43bea5a..a162e4e10c71 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -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; @@ -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); @@ -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 + } } |
