Merge "Animate the priority ring in the onboarding" into rvc-dev am: 675d4a78cb

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11795077

Change-Id: Id6fad7790eb0a8c70568acf4444af23a62b3f539
This commit is contained in:
TreeHugger Robot
2020-06-10 15:03:28 +00:00
committed by Automerger Merge Worker
6 changed files with 155 additions and 14 deletions

View File

@@ -3957,6 +3957,13 @@
<java-symbol type="id" name="conversation_unread_count" />
<java-symbol type="string" name="unread_convo_overflow" />
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Conversation.AppName" />
<java-symbol type="drawable" name="conversation_badge_background" />
<java-symbol type="drawable" name="conversation_badge_ring" />
<java-symbol type="color" name="conversation_important_highlight" />
<java-symbol type="dimen" name="importance_ring_stroke_width" />
<java-symbol type="dimen" name="importance_ring_anim_max_stroke_width" />
<java-symbol type="dimen" name="importance_ring_size" />
<java-symbol type="dimen" name="conversation_icon_size_badged" />
<!-- Intent resolver and share sheet -->
<java-symbol type="string" name="resolver_personal_tab" />

View File

@@ -86,7 +86,7 @@ public class ConversationIconFactory extends BaseIconFactory {
/**
* Returns the conversation info drawable
*/
private Drawable getBaseIconDrawable(ShortcutInfo shortcutInfo) {
public Drawable getBaseIconDrawable(ShortcutInfo shortcutInfo) {
return mLauncherApps.getShortcutIconDrawable(shortcutInfo, mFillResIconDpi);
}
@@ -94,7 +94,7 @@ public class ConversationIconFactory extends BaseIconFactory {
* Get the {@link Drawable} that represents the app icon, badged with the work profile icon
* if appropriate.
*/
private Drawable getAppBadge(String packageName, int userId) {
public Drawable getAppBadge(String packageName, int userId) {
Drawable badge = null;
try {
final ApplicationInfo appInfo = mPackageManager.getApplicationInfoAsUser(

View File

@@ -38,11 +38,61 @@
android:background="@drawable/rounded_bg_full"
>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="12dp"
android:layout_gravity="center_horizontal"
>
<!-- Big icon: 52x52, 12dp padding left + top, 16dp padding right -->
<ImageView
android:id="@+id/conversation_icon"
android:layout_width="@dimen/notification_guts_conversation_icon_size"
android:layout_height="@dimen/notification_guts_conversation_icon_size"
android:layout_gravity="center_horizontal" />
android:layout_width="@*android:dimen/conversation_avatar_size"
android:layout_height="@*android:dimen/conversation_avatar_size"
android:scaleType="centerCrop"
android:importantForAccessibility="no"
/>
<FrameLayout
android:id="@+id/conversation_icon_badge"
android:layout_width="@*android:dimen/conversation_icon_size_badged"
android:layout_height="@*android:dimen/conversation_icon_size_badged"
android:layout_marginLeft="@*android:dimen/conversation_badge_side_margin"
android:layout_marginTop="@*android:dimen/conversation_badge_side_margin"
android:clipChildren="false"
android:clipToPadding="false"
>
<ImageView
android:id="@+id/conversation_icon_badge_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="@*android:drawable/conversation_badge_background"
android:forceHasOverlappingRendering="false"
/>
<ImageView
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:layout_gravity="center"
android:forceHasOverlappingRendering="false"
/>
<ImageView
android:id="@+id/conversation_icon_badge_ring"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@*android:drawable/conversation_badge_ring"
android:forceHasOverlappingRendering="false"
android:clipToPadding="false"
android:scaleType="center"
/>
</FrameLayout>
</FrameLayout>
<TextView
android:id="@+id/title"

View File

@@ -124,7 +124,7 @@ public final class Prefs {
String HAS_SEEN_BUBBLES_MANAGE_EDUCATION = "HasSeenBubblesManageOnboarding";
String CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT = "ControlsStructureSwipeTooltipCount";
/** Tracks whether the user has seen the onboarding screen for priority conversations */
String HAS_SEEN_PRIORITY_ONBOARDING = "HaveShownPriorityOnboarding";
String HAS_SEEN_PRIORITY_ONBOARDING = "HasUserSeenPriorityOnboarding";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {

View File

@@ -44,6 +44,7 @@ import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
@@ -540,7 +541,9 @@ public class NotificationConversationInfo extends LinearLayout implements
.setView(onboardingView)
.setIgnoresDnd(ignoreDnd)
.setShowsAsBubble(showAsBubble)
.setIcon(((ImageView) findViewById(R.id.conversation_icon)).getDrawable())
.setIcon(mIconFactory.getBaseIconDrawable(mShortcutInfo))
.setBadge(mIconFactory.getAppBadge(
mPackageName, UserHandle.getUserId(mSbn.getUid())))
.setOnSettingsClick(mOnConversationSettingsClickListener)
.build();

View File

@@ -16,41 +16,57 @@
package com.android.systemui.statusbar.notification.row
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.text.SpannableStringBuilder
import android.text.style.BulletSpan
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.Window
import android.view.WindowInsets.Type.statusBars
import android.view.WindowManager
import android.view.animation.Interpolator
import android.view.animation.PathInterpolator
import android.widget.ImageView
import android.widget.TextView
import com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN
import com.android.systemui.Prefs
import com.android.systemui.R
import com.android.systemui.statusbar.notification.row.NotificationConversationInfo.OnConversationSettingsClickListener
import javax.inject.Inject
/**
* Controller to handle presenting the priority conversations onboarding dialog
*/
class PriorityOnboardingDialogController @Inject constructor(
val view: View,
val context: Context,
val ignoresDnd: Boolean,
val showsAsBubble: Boolean,
val icon : Drawable,
val onConversationSettingsClickListener : OnConversationSettingsClickListener
val view: View,
val context: Context,
private val ignoresDnd: Boolean,
private val showsAsBubble: Boolean,
val icon : Drawable,
private val onConversationSettingsClickListener : OnConversationSettingsClickListener,
val badge : Drawable
) {
private lateinit var dialog: Dialog
private val OVERSHOOT: Interpolator = PathInterpolator(0.4f, 0f, 0.2f, 1.4f)
private val IMPORTANCE_ANIM_DELAY = 150L
private val IMPORTANCE_ANIM_GROW_DURATION = 250L
private val IMPORTANCE_ANIM_SHRINK_DURATION = 200L
private val IMPORTANCE_ANIM_SHRINK_DELAY = 25L
fun init() {
initDialog()
@@ -81,6 +97,7 @@ class PriorityOnboardingDialogController @Inject constructor(
private lateinit var icon: Drawable
private lateinit var onConversationSettingsClickListener
: OnConversationSettingsClickListener
private lateinit var badge : Drawable
fun setView(v: View): Builder {
view = v
@@ -106,6 +123,10 @@ class PriorityOnboardingDialogController @Inject constructor(
icon = draw
return this
}
fun setBadge(badge : Drawable) : Builder {
this.badge = badge
return this
}
fun setOnSettingsClick(onClick : OnConversationSettingsClickListener) : Builder {
onConversationSettingsClickListener = onClick
@@ -115,7 +136,7 @@ class PriorityOnboardingDialogController @Inject constructor(
fun build(): PriorityOnboardingDialogController {
val controller = PriorityOnboardingDialogController(
view, context, ignoresDnd, showAsBubble, icon,
onConversationSettingsClickListener)
onConversationSettingsClickListener, badge)
return controller
}
}
@@ -143,6 +164,65 @@ class PriorityOnboardingDialogController @Inject constructor(
}
findViewById<ImageView>(R.id.conversation_icon)?.setImageDrawable(icon)
findViewById<ImageView>(R.id.icon)?.setImageDrawable(badge)
val mImportanceRingView = findViewById<ImageView>(R.id.conversation_icon_badge_ring)
val conversationIconBadgeBg = findViewById<ImageView>(R.id.conversation_icon_badge_bg)
val ring: GradientDrawable = mImportanceRingView.drawable as GradientDrawable
ring.mutate()
val bg = conversationIconBadgeBg.drawable as GradientDrawable
bg.mutate()
val ringColor = context.getResources()
.getColor(com.android.internal.R.color.conversation_important_highlight)
val standardThickness = context.resources.getDimensionPixelSize(
com.android.internal.R.dimen.importance_ring_stroke_width)
val largeThickness = context.resources.getDimensionPixelSize(
com.android.internal.R.dimen.importance_ring_anim_max_stroke_width)
val standardSize = context.resources.getDimensionPixelSize(
com.android.internal.R.dimen.importance_ring_size)
val baseSize = standardSize - standardThickness * 2
val largeSize = baseSize + largeThickness * 2
val bgSize = context.resources.getDimensionPixelSize(
com.android.internal.R.dimen.conversation_icon_size_badged)
val animatorUpdateListener: ValueAnimator.AnimatorUpdateListener
= ValueAnimator.AnimatorUpdateListener { animation ->
val strokeWidth = animation.animatedValue as Int
ring.setStroke(strokeWidth, ringColor)
val newSize = baseSize + strokeWidth * 2
ring.setSize(newSize, newSize)
mImportanceRingView.invalidate()
}
val growAnimation: ValueAnimator = ValueAnimator.ofInt(0, largeThickness)
growAnimation.interpolator = LINEAR_OUT_SLOW_IN
growAnimation.duration = IMPORTANCE_ANIM_GROW_DURATION
growAnimation.addUpdateListener(animatorUpdateListener)
val shrinkAnimation: ValueAnimator
= ValueAnimator.ofInt(largeThickness, standardThickness)
shrinkAnimation.duration = IMPORTANCE_ANIM_SHRINK_DURATION
shrinkAnimation.startDelay = IMPORTANCE_ANIM_SHRINK_DELAY
shrinkAnimation.interpolator = OVERSHOOT
shrinkAnimation.addUpdateListener(animatorUpdateListener)
shrinkAnimation.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
// Shrink the badge bg so that it doesn't peek behind the animation
bg.setSize(baseSize, baseSize);
conversationIconBadgeBg.invalidate();
}
override fun onAnimationEnd(animation: Animator?) {
// Reset bg back to normal size
bg.setSize(bgSize, bgSize);
conversationIconBadgeBg.invalidate();
}
})
val anims = AnimatorSet()
anims.startDelay = IMPORTANCE_ANIM_DELAY
anims.playSequentially(growAnimation, shrinkAnimation)
val gapWidth = dialog.context.getResources().getDimensionPixelSize(
R.dimen.conversation_onboarding_bullet_gap_width)
@@ -180,6 +260,7 @@ class PriorityOnboardingDialogController @Inject constructor(
height = WRAP_CONTENT
}
}
anims.start()
}
}