Loading core/java/com/android/internal/widget/ConversationLayout.java +74 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_ import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN; import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -36,6 +40,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Parcelable; Loading Loading @@ -93,8 +98,12 @@ public class ConversationLayout extends FrameLayout public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); public static final Interpolator OVERSHOOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f); public static final OnLayoutChangeListener MESSAGING_PROPERTY_ANIMATOR = new MessagingPropertyAnimator(); public static final int IMPORTANCE_ANIM_GROW_DURATION = 250; public static final int IMPORTANCE_ANIM_SHRINK_DURATION = 200; public static final int IMPORTANCE_ANIM_SHRINK_DELAY = 25; private List<MessagingMessage> mMessages = new ArrayList<>(); private List<MessagingMessage> mHistoricMessages = new ArrayList<>(); private MessagingLinearLayout mMessagingLinearLayout; Loading Loading @@ -331,14 +340,74 @@ public class ConversationLayout extends FrameLayout mNameReplacement = nameReplacement; } /** * Sets this conversation as "important", adding some additional UI treatment. */ /** Sets this conversation as "important", adding some additional UI treatment. */ @RemotableViewMethod public void setIsImportantConversation(boolean isImportantConversation) { setIsImportantConversation(isImportantConversation, false); } /** @hide **/ public void setIsImportantConversation(boolean isImportantConversation, boolean animate) { mImportantConversation = isImportantConversation; mImportanceRingView.setVisibility(isImportantConversation && mIcon.getVisibility() != GONE ? VISIBLE : GONE); mImportanceRingView.setVisibility(isImportantConversation && mIcon.getVisibility() != GONE ? VISIBLE : GONE); if (animate && isImportantConversation) { GradientDrawable ring = (GradientDrawable) mImportanceRingView.getDrawable(); ring.mutate(); GradientDrawable bg = (GradientDrawable) mConversationIconBadgeBg.getDrawable(); bg.mutate(); int ringColor = getResources() .getColor(R.color.conversation_important_highlight); int standardThickness = getResources() .getDimensionPixelSize(R.dimen.importance_ring_stroke_width); int largeThickness = getResources() .getDimensionPixelSize(R.dimen.importance_ring_anim_max_stroke_width); int standardSize = getResources().getDimensionPixelSize( R.dimen.importance_ring_size); int baseSize = standardSize - standardThickness * 2; int bgSize = getResources() .getDimensionPixelSize(R.dimen.conversation_icon_size_badged); ValueAnimator.AnimatorUpdateListener animatorUpdateListener = animation -> { int strokeWidth = Math.round((float) animation.getAnimatedValue()); ring.setStroke(strokeWidth, ringColor); int newSize = baseSize + strokeWidth * 2; ring.setSize(newSize, newSize); mImportanceRingView.invalidate(); }; ValueAnimator growAnimation = ValueAnimator.ofFloat(0, largeThickness); growAnimation.setInterpolator(LINEAR_OUT_SLOW_IN); growAnimation.setDuration(IMPORTANCE_ANIM_GROW_DURATION); growAnimation.addUpdateListener(animatorUpdateListener); ValueAnimator shrinkAnimation = ValueAnimator.ofFloat(largeThickness, standardThickness); shrinkAnimation.setDuration(IMPORTANCE_ANIM_SHRINK_DURATION); shrinkAnimation.setStartDelay(IMPORTANCE_ANIM_SHRINK_DELAY); shrinkAnimation.setInterpolator(OVERSHOOT); shrinkAnimation.addUpdateListener(animatorUpdateListener); shrinkAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { // Shrink the badge bg so that it doesn't peek behind the animation bg.setSize(baseSize, baseSize); mConversationIconBadgeBg.invalidate(); } @Override public void onAnimationEnd(Animator animation) { // Reset bg back to normal size bg.setSize(bgSize, bgSize); mConversationIconBadgeBg.invalidate(); } }); AnimatorSet anims = new AnimatorSet(); anims.playSequentially(growAnimation, shrinkAnimation); anims.start(); } } public boolean isImportantConversation() { Loading core/res/res/drawable/conversation_badge_background.xml +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ android:color="#ffffff"/> <size android:width="26dp" android:height="26dp"/> android:width="20dp" android:height="20dp"/> </shape> core/res/res/drawable/conversation_badge_ring.xml +8 −7 Original line number Diff line number Diff line Loading @@ -16,17 +16,18 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/transparent"/> android:shape="oval" > <solid android:color="@color/transparent" /> <stroke android:color="@color/conversation_important_highlight" android:width="2dp"/> android:width="@dimen/importance_ring_stroke_width" /> <size android:width="26dp" android:height="26dp"/> android:width="@dimen/importance_ring_size" android:height="@dimen/importance_ring_size" /> </shape> core/res/res/layout/notification_template_material_conversation.xml +11 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" android:layout_gravity="top|center_horizontal" > Loading @@ -63,13 +65,17 @@ android:layout_height="@dimen/conversation_icon_size_badged" android:layout_marginLeft="@dimen/conversation_badge_side_margin" android:layout_marginTop="@dimen/conversation_badge_side_margin" android:clipChildren="false" android:clipToPadding="false" > <com.android.internal.widget.CachingIconView android:id="@+id/conversation_icon_badge_bg" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:src="@drawable/conversation_badge_background" android:forceHasOverlappingRendering="false" android:scaleType="center" /> <com.android.internal.widget.CachingIconView android:id="@+id/icon" Loading @@ -81,11 +87,14 @@ /> <com.android.internal.widget.CachingIconView android:id="@+id/conversation_icon_badge_ring" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/conversation_badge_ring" android:visibility="gone" android:forceHasOverlappingRendering="false" android:clipToPadding="false" android:scaleType="center" /> </FrameLayout> </FrameLayout> Loading core/res/res/values/dimens.xml +6 −0 Original line number Diff line number Diff line Loading @@ -720,6 +720,12 @@ <dimen name="conversation_face_pile_protection_width_expanded">1dp</dimen> <!-- The padding of the expanded message container--> <dimen name="expanded_group_conversation_message_padding">14dp</dimen> <!-- The stroke width of the ring used to visually mark a conversation as important --> <dimen name="importance_ring_stroke_width">2dp</dimen> <!-- The maximum stroke width used for the animation shown when a conversation is marked as important --> <dimen name="importance_ring_anim_max_stroke_width">10dp</dimen> <!-- The size of the importance ring --> <dimen name="importance_ring_size">20dp</dimen> <!-- The top padding of the conversation icon container in the regular state--> <dimen name="conversation_icon_container_top_padding">9dp</dimen> Loading Loading
core/java/com/android/internal/widget/ConversationLayout.java +74 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_ import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN; import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -36,6 +40,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Parcelable; Loading Loading @@ -93,8 +98,12 @@ public class ConversationLayout extends FrameLayout public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); public static final Interpolator OVERSHOOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f); public static final OnLayoutChangeListener MESSAGING_PROPERTY_ANIMATOR = new MessagingPropertyAnimator(); public static final int IMPORTANCE_ANIM_GROW_DURATION = 250; public static final int IMPORTANCE_ANIM_SHRINK_DURATION = 200; public static final int IMPORTANCE_ANIM_SHRINK_DELAY = 25; private List<MessagingMessage> mMessages = new ArrayList<>(); private List<MessagingMessage> mHistoricMessages = new ArrayList<>(); private MessagingLinearLayout mMessagingLinearLayout; Loading Loading @@ -331,14 +340,74 @@ public class ConversationLayout extends FrameLayout mNameReplacement = nameReplacement; } /** * Sets this conversation as "important", adding some additional UI treatment. */ /** Sets this conversation as "important", adding some additional UI treatment. */ @RemotableViewMethod public void setIsImportantConversation(boolean isImportantConversation) { setIsImportantConversation(isImportantConversation, false); } /** @hide **/ public void setIsImportantConversation(boolean isImportantConversation, boolean animate) { mImportantConversation = isImportantConversation; mImportanceRingView.setVisibility(isImportantConversation && mIcon.getVisibility() != GONE ? VISIBLE : GONE); mImportanceRingView.setVisibility(isImportantConversation && mIcon.getVisibility() != GONE ? VISIBLE : GONE); if (animate && isImportantConversation) { GradientDrawable ring = (GradientDrawable) mImportanceRingView.getDrawable(); ring.mutate(); GradientDrawable bg = (GradientDrawable) mConversationIconBadgeBg.getDrawable(); bg.mutate(); int ringColor = getResources() .getColor(R.color.conversation_important_highlight); int standardThickness = getResources() .getDimensionPixelSize(R.dimen.importance_ring_stroke_width); int largeThickness = getResources() .getDimensionPixelSize(R.dimen.importance_ring_anim_max_stroke_width); int standardSize = getResources().getDimensionPixelSize( R.dimen.importance_ring_size); int baseSize = standardSize - standardThickness * 2; int bgSize = getResources() .getDimensionPixelSize(R.dimen.conversation_icon_size_badged); ValueAnimator.AnimatorUpdateListener animatorUpdateListener = animation -> { int strokeWidth = Math.round((float) animation.getAnimatedValue()); ring.setStroke(strokeWidth, ringColor); int newSize = baseSize + strokeWidth * 2; ring.setSize(newSize, newSize); mImportanceRingView.invalidate(); }; ValueAnimator growAnimation = ValueAnimator.ofFloat(0, largeThickness); growAnimation.setInterpolator(LINEAR_OUT_SLOW_IN); growAnimation.setDuration(IMPORTANCE_ANIM_GROW_DURATION); growAnimation.addUpdateListener(animatorUpdateListener); ValueAnimator shrinkAnimation = ValueAnimator.ofFloat(largeThickness, standardThickness); shrinkAnimation.setDuration(IMPORTANCE_ANIM_SHRINK_DURATION); shrinkAnimation.setStartDelay(IMPORTANCE_ANIM_SHRINK_DELAY); shrinkAnimation.setInterpolator(OVERSHOOT); shrinkAnimation.addUpdateListener(animatorUpdateListener); shrinkAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { // Shrink the badge bg so that it doesn't peek behind the animation bg.setSize(baseSize, baseSize); mConversationIconBadgeBg.invalidate(); } @Override public void onAnimationEnd(Animator animation) { // Reset bg back to normal size bg.setSize(bgSize, bgSize); mConversationIconBadgeBg.invalidate(); } }); AnimatorSet anims = new AnimatorSet(); anims.playSequentially(growAnimation, shrinkAnimation); anims.start(); } } public boolean isImportantConversation() { Loading
core/res/res/drawable/conversation_badge_background.xml +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ android:color="#ffffff"/> <size android:width="26dp" android:height="26dp"/> android:width="20dp" android:height="20dp"/> </shape>
core/res/res/drawable/conversation_badge_ring.xml +8 −7 Original line number Diff line number Diff line Loading @@ -16,17 +16,18 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/transparent"/> android:shape="oval" > <solid android:color="@color/transparent" /> <stroke android:color="@color/conversation_important_highlight" android:width="2dp"/> android:width="@dimen/importance_ring_stroke_width" /> <size android:width="26dp" android:height="26dp"/> android:width="@dimen/importance_ring_size" android:height="@dimen/importance_ring_size" /> </shape>
core/res/res/layout/notification_template_material_conversation.xml +11 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" android:layout_gravity="top|center_horizontal" > Loading @@ -63,13 +65,17 @@ android:layout_height="@dimen/conversation_icon_size_badged" android:layout_marginLeft="@dimen/conversation_badge_side_margin" android:layout_marginTop="@dimen/conversation_badge_side_margin" android:clipChildren="false" android:clipToPadding="false" > <com.android.internal.widget.CachingIconView android:id="@+id/conversation_icon_badge_bg" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:src="@drawable/conversation_badge_background" android:forceHasOverlappingRendering="false" android:scaleType="center" /> <com.android.internal.widget.CachingIconView android:id="@+id/icon" Loading @@ -81,11 +87,14 @@ /> <com.android.internal.widget.CachingIconView android:id="@+id/conversation_icon_badge_ring" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/conversation_badge_ring" android:visibility="gone" android:forceHasOverlappingRendering="false" android:clipToPadding="false" android:scaleType="center" /> </FrameLayout> </FrameLayout> Loading
core/res/res/values/dimens.xml +6 −0 Original line number Diff line number Diff line Loading @@ -720,6 +720,12 @@ <dimen name="conversation_face_pile_protection_width_expanded">1dp</dimen> <!-- The padding of the expanded message container--> <dimen name="expanded_group_conversation_message_padding">14dp</dimen> <!-- The stroke width of the ring used to visually mark a conversation as important --> <dimen name="importance_ring_stroke_width">2dp</dimen> <!-- The maximum stroke width used for the animation shown when a conversation is marked as important --> <dimen name="importance_ring_anim_max_stroke_width">10dp</dimen> <!-- The size of the importance ring --> <dimen name="importance_ring_size">20dp</dimen> <!-- The top padding of the conversation icon container in the regular state--> <dimen name="conversation_icon_container_top_padding">9dp</dimen> Loading