diff options
Diffstat (limited to 'core/java')
5 files changed, 148 insertions, 18 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e137acf4dc70..9b42fa2012e1 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5817,7 +5817,7 @@ public class Notification implements Parcelable PorterDuff.Mode.SRC_ATOP); } - contentView.setInt(R.id.notification_header, "setOriginalIconColor", + contentView.setInt(R.id.icon, "setOriginalIconColor", colorable ? color : NotificationHeaderView.NO_COLOR); } diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index 18e0132e2c4e..0359f3b4fde7 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -65,7 +65,6 @@ public class NotificationHeaderView extends ViewGroup { private View mMicIcon; private View mAppOps; private View mAudiblyAlertedIcon; - private int mIconColor; private boolean mExpanded; private boolean mShowExpandButtonAtEnd; private boolean mShowWorkBadgeAtEnd; @@ -315,13 +314,8 @@ public class NotificationHeaderView extends ViewGroup { updateTouchListener(); } - @RemotableViewMethod - public void setOriginalIconColor(int color) { - mIconColor = color; - } - public int getOriginalIconColor() { - return mIconColor; + return mIcon.getOriginalIconColor(); } public int getOriginalNotificationColor() { diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java index bd0623e1144e..84cde1b84e14 100644 --- a/core/java/com/android/internal/widget/CachingIconView.java +++ b/core/java/com/android/internal/widget/CachingIconView.java @@ -46,6 +46,9 @@ public class CachingIconView extends ImageView { private boolean mForceHidden; private int mDesiredVisibility; private Consumer<Integer> mOnVisibilityChangedListener; + private Consumer<Boolean> mOnForceHiddenChangedListener; + private int mIconColor; + private boolean mWillBeForceHidden; @UnsupportedAppUsage public CachingIconView(Context context, @Nullable AttributeSet attrs) { @@ -184,10 +187,18 @@ public class CachingIconView extends ImageView { /** * Set the icon to be forcibly hidden, even when it's visibility is changed to visible. + * This is necessary since we still want to keep certain views hidden when their visibility + * is modified from other sources like the shelf. */ public void setForceHidden(boolean forceHidden) { - mForceHidden = forceHidden; - updateVisibility(); + if (forceHidden != mForceHidden) { + mForceHidden = forceHidden; + mWillBeForceHidden = false; + updateVisibility(); + if (mOnForceHiddenChangedListener != null) { + mOnForceHiddenChangedListener.accept(forceHidden); + } + } } @Override @@ -209,4 +220,38 @@ public class CachingIconView extends ImageView { public void setOnVisibilityChangedListener(Consumer<Integer> listener) { mOnVisibilityChangedListener = listener; } + + public void setOnForceHiddenChangedListener(Consumer<Boolean> listener) { + mOnForceHiddenChangedListener = listener; + } + + + public boolean isForceHidden() { + return mForceHidden; + } + + @RemotableViewMethod + public void setOriginalIconColor(int color) { + mIconColor = color; + } + + public int getOriginalIconColor() { + return mIconColor; + } + + /** + * @return if the view will be forceHidden after an animation + */ + public boolean willBeForceHidden() { + return mWillBeForceHidden; + } + + /** + * Set that this view will be force hidden after an animation + * + * @param forceHidden if it will be forcehidden + */ + public void setWillBeForceHidden(boolean forceHidden) { + mWillBeForceHidden = forceHidden; + } } diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index bedf55d52391..1336ec412cdb 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -18,6 +18,8 @@ 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 static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN; +import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT; import android.annotation.AttrRes; import android.annotation.NonNull; @@ -106,7 +108,7 @@ public class ConversationLayout extends FrameLayout private CharSequence mNameReplacement; private boolean mIsCollapsed; private ImageResolver mImageResolver; - private ImageView mConversationIcon; + private CachingIconView mConversationIcon; private View mConversationIconContainer; private int mConversationIconTopPadding; private int mConversationIconTopPaddingExpandedGroup; @@ -114,7 +116,7 @@ public class ConversationLayout extends FrameLayout private int mExpandedGroupMessagePaddingNoAppName; private TextView mConversationText; private View mConversationIconBadge; - private ImageView mConversationIconBadgeBg; + private CachingIconView mConversationIconBadgeBg; private Icon mLargeIcon; private View mExpandButtonContainer; private ViewGroup mExpandButtonAndContentContainer; @@ -125,7 +127,7 @@ public class ConversationLayout extends FrameLayout private int mConversationAvatarSize; private int mConversationAvatarSizeExpanded; private CachingIconView mIcon; - private View mImportanceRingView; + private CachingIconView mImportanceRingView; private int mExpandedGroupSideMargin; private int mExpandedGroupSideMarginFacePile; private View mConversationFacePile; @@ -140,11 +142,15 @@ public class ConversationLayout extends FrameLayout private int mContentMarginEnd; private Rect mMessagingClipRect; private ObservableTextView mAppName; + private ViewGroup mActions; + private int mConversationContentStart; + private int mInternalButtonPadding; private boolean mAppNameGone; private int mFacePileAvatarSize; private int mFacePileAvatarSizeExpandedGroup; private int mFacePileProtectionWidth; private int mFacePileProtectionWidthExpanded; + private boolean mImportantConversation; public ConversationLayout(@NonNull Context context) { super(context); @@ -168,6 +174,7 @@ public class ConversationLayout extends FrameLayout protected void onFinishInflate() { super.onFinishInflate(); mMessagingLinearLayout = findViewById(R.id.notification_messaging); + mActions = findViewById(R.id.actions); 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 @@ -186,9 +193,41 @@ public class ConversationLayout extends FrameLayout mConversationIconBadge = findViewById(R.id.conversation_icon_badge); mConversationIconBadgeBg = findViewById(R.id.conversation_icon_badge_bg); mIcon.setOnVisibilityChangedListener((visibility) -> { - // Always keep the badge visibility in sync with the icon. This is necessary in cases - // Where the icon is being hidden externally like in group children. - mConversationIconBadge.setVisibility(visibility); + + // Let's hide the background directly or in an animated way + boolean isGone = visibility == GONE; + int oldVisibility = mConversationIconBadgeBg.getVisibility(); + boolean wasGone = oldVisibility == GONE; + if (wasGone != isGone) { + // Keep the badge gone state in sync with the icon. This is necessary in cases + // Where the icon is being hidden externally like in group children. + mConversationIconBadgeBg.animate().cancel(); + mConversationIconBadgeBg.setVisibility(visibility); + } + + // Let's handle the importance ring which can also be be gone normally + oldVisibility = mImportanceRingView.getVisibility(); + wasGone = oldVisibility == GONE; + visibility = !mImportantConversation ? GONE : visibility; + isGone = visibility == GONE; + if (wasGone != isGone) { + // Keep the badge visibility in sync with the icon. This is necessary in cases + // Where the icon is being hidden externally like in group children. + mImportanceRingView.animate().cancel(); + mImportanceRingView.setVisibility(visibility); + } + }); + // When the small icon is gone, hide the rest of the badge + mIcon.setOnForceHiddenChangedListener((forceHidden) -> { + animateViewForceHidden(mConversationIconBadgeBg, forceHidden); + animateViewForceHidden(mImportanceRingView, forceHidden); + }); + + // When the conversation icon is gone, hide the whole badge + mConversationIcon.setOnForceHiddenChangedListener((forceHidden) -> { + animateViewForceHidden(mConversationIconBadgeBg, forceHidden); + animateViewForceHidden(mImportanceRingView, forceHidden); + animateViewForceHidden(mIcon, forceHidden); }); mConversationText = findViewById(R.id.conversation_text); mExpandButtonContainer = findViewById(R.id.expand_button_container); @@ -238,6 +277,33 @@ public class ConversationLayout extends FrameLayout mAppName.setOnVisibilityChangedListener((visibility) -> { onAppNameVisibilityChanged(); }); + mConversationContentStart = getResources().getDimensionPixelSize( + R.dimen.conversation_content_start); + mInternalButtonPadding + = getResources().getDimensionPixelSize(R.dimen.button_padding_horizontal_material) + + getResources().getDimensionPixelSize(R.dimen.button_inset_horizontal_material); + } + + private void animateViewForceHidden(CachingIconView view, boolean forceHidden) { + boolean nowForceHidden = view.willBeForceHidden() || view.isForceHidden(); + if (forceHidden == nowForceHidden) { + // We are either already forceHidden or will be + return; + } + view.animate().cancel(); + view.setWillBeForceHidden(forceHidden); + view.animate() + .scaleX(forceHidden ? 0.5f : 1.0f) + .scaleY(forceHidden ? 0.5f : 1.0f) + .alpha(forceHidden ? 0.0f : 1.0f) + .setInterpolator(forceHidden ? ALPHA_OUT : ALPHA_IN) + .setDuration(160); + if (view.getVisibility() != VISIBLE) { + view.setForceHidden(forceHidden); + } else { + view.animate().withEndAction(() -> view.setForceHidden(forceHidden)); + } + view.animate().start(); } @RemotableViewMethod @@ -255,9 +321,14 @@ public class ConversationLayout extends FrameLayout */ @RemotableViewMethod public void setIsImportantConversation(boolean isImportantConversation) { + mImportantConversation = isImportantConversation; mImportanceRingView.setVisibility(isImportantConversation ? VISIBLE : GONE); } + public boolean isImportantConversation() { + return mImportantConversation; + } + /** * Set this layout to show the collapsed representation. * @@ -363,7 +434,6 @@ public class ConversationLayout extends FrameLayout private void updateConversationLayout() { // Set avatar and name CharSequence conversationText = mConversationTitle; - // TODO: display the secondary text somewhere if (mIsOneToOne) { // Let's resolve the icon / text from the last sender mConversationIcon.setVisibility(VISIBLE); @@ -418,6 +488,27 @@ public class ConversationLayout extends FrameLayout updateIconPositionAndSize(); updateImageMessages(); updatePaddingsBasedOnContentAvailability(); + updateActionListPadding(); + } + + private void updateActionListPadding() { + if (mActions == null) { + return; + } + View firstAction = mActions.getChildAt(0); + if (firstAction != null) { + // Let's visually position the first action where the content starts + int paddingStart = mConversationContentStart; + + MarginLayoutParams layoutParams = (MarginLayoutParams) firstAction.getLayoutParams(); + paddingStart -= layoutParams.getMarginStart(); + paddingStart -= mInternalButtonPadding; + + mActions.setPaddingRelative(paddingStart, + mActions.getPaddingTop(), + mActions.getPaddingEnd(), + mActions.getPaddingBottom()); + } } private void updateImageMessages() { diff --git a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java index 7703cb0f13db..a3a75c098a00 100644 --- a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java +++ b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java @@ -32,7 +32,7 @@ import com.android.internal.R; */ public class MessagingPropertyAnimator implements View.OnLayoutChangeListener { private static final long APPEAR_ANIMATION_LENGTH = 210; - private static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); + public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f); private static final int TAG_TOP_ANIMATOR = R.id.tag_top_animator; private static final int TAG_TOP = R.id.tag_top_override; |
