Loading packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java +1 −2 Original line number Diff line number Diff line Loading @@ -652,8 +652,7 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll CrossFadeHelper.fadeOut( mLayout, mFadeOutDuration, /* delay= */ 0, /* endRunnable= */ null); /* delay= */ 0); } } Loading packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java +64 −12 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.statusbar; import android.animation.Animator; import android.view.View; import android.view.ViewPropertyAnimator; import androidx.annotation.Nullable; Loading @@ -31,32 +33,58 @@ public class CrossFadeHelper { public static final long ANIMATION_DURATION_LENGTH = 210; public static void fadeOut(final View view) { fadeOut(view, null); fadeOut(view, (Runnable) null); } public static void fadeOut(final View view, final Runnable endRunnable) { fadeOut(view, ANIMATION_DURATION_LENGTH, 0, endRunnable); } public static void fadeOut(final View view, final Animator.AnimatorListener listener) { fadeOut(view, ANIMATION_DURATION_LENGTH, 0, listener); } public static void fadeOut(final View view, long duration, int delay) { fadeOut(view, duration, delay, (Runnable) null); } public static void fadeOut(final View view, long duration, int delay, final Runnable endRunnable) { @Nullable final Runnable endRunnable) { view.animate().cancel(); view.animate() .alpha(0f) .setDuration(duration) .setInterpolator(Interpolators.ALPHA_OUT) .setStartDelay(delay) .withEndAction(new Runnable() { @Override public void run() { .withEndAction(() -> { if (endRunnable != null) { endRunnable.run(); } if (view.getVisibility() != View.GONE) { view.setVisibility(View.INVISIBLE); } }); if (view.hasOverlappingRendering()) { view.animate().withLayer(); } } public static void fadeOut(final View view, long duration, int delay, @Nullable final Animator.AnimatorListener listener) { view.animate().cancel(); ViewPropertyAnimator animator = view.animate() .alpha(0f) .setDuration(duration) .setInterpolator(Interpolators.ALPHA_OUT) .setStartDelay(delay) .withEndAction(() -> { if (view.getVisibility() != View.GONE) { view.setVisibility(View.INVISIBLE); } }); if (listener != null) { animator.setListener(listener); } if (view.hasOverlappingRendering()) { view.animate().withLayer(); } Loading Loading @@ -119,8 +147,12 @@ public class CrossFadeHelper { fadeIn(view, ANIMATION_DURATION_LENGTH, /* delay= */ 0, endRunnable); } public static void fadeIn(final View view, Animator.AnimatorListener listener) { fadeIn(view, ANIMATION_DURATION_LENGTH, /* delay= */ 0, listener); } public static void fadeIn(final View view, long duration, int delay) { fadeIn(view, duration, delay, /* endRunnable= */ null); fadeIn(view, duration, delay, /* endRunnable= */ (Runnable) null); } public static void fadeIn(final View view, long duration, int delay, Loading @@ -141,6 +173,26 @@ public class CrossFadeHelper { } } public static void fadeIn(final View view, long duration, int delay, @Nullable Animator.AnimatorListener listener) { view.animate().cancel(); if (view.getVisibility() == View.INVISIBLE) { view.setAlpha(0.0f); view.setVisibility(View.VISIBLE); } ViewPropertyAnimator animator = view.animate() .alpha(1f) .setDuration(duration) .setStartDelay(delay) .setInterpolator(Interpolators.ALPHA_IN); if (listener != null) { animator.setListener(listener); } if (view.hasOverlappingRendering() && view.getLayerType() != View.LAYER_TYPE_HARDWARE) { view.animate().withLayer(); } } public static void fadeIn(View view, float fadeInAmount) { fadeIn(view, fadeInAmount, false /* remap */); } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +45 −27 Original line number Diff line number Diff line Loading @@ -15,8 +15,11 @@ */ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.graphics.Rect import android.view.View import android.view.ViewPropertyAnimator import android.widget.FrameLayout import androidx.collection.ArrayMap import androidx.lifecycle.Lifecycle Loading Loading @@ -46,6 +49,9 @@ import com.android.systemui.util.children import com.android.systemui.util.kotlin.mapValuesNotNullTo import com.android.systemui.util.kotlin.sample import com.android.systemui.util.kotlin.stateFlow import com.android.systemui.util.ui.isAnimating import com.android.systemui.util.ui.stopAnimating import com.android.systemui.util.ui.value import javax.inject.Inject import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.coroutineScope Loading Loading @@ -73,16 +79,24 @@ object NotificationIconContainerViewBinder { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } launch { viewModel.isDozing.collect { (isDozing, animate) -> val animateIfNotBlanking = animate && !dozeParameters.displayNeedsBlanking viewModel.isDozing.collect { isDozing -> if (isDozing.isAnimating) { val animate = !dozeParameters.displayNeedsBlanking view.setDozing( /* dozing = */ isDozing, /* fade = */ animateIfNotBlanking, /* dozing = */ isDozing.value, /* fade = */ animate, /* delay = */ 0, /* endRunnable = */ isDozing::stopAnimating, ) } else { view.setDozing( /* dozing = */ isDozing.value, /* fade= */ false, /* delay= */ 0, /* endRunnable = */ viewModel::completeDozeAnimation, ) } } } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder launch { Loading @@ -92,7 +106,6 @@ object NotificationIconContainerViewBinder { configuration, featureFlags, screenOffAnimationController, onAnimationEnd = viewModel::completeVisibilityAnimation, ) } launch { Loading Loading @@ -225,33 +238,38 @@ object NotificationIconContainerViewBinder { configuration: ConfigurationState, featureFlags: FeatureFlagsClassic, screenOffAnimationController: ScreenOffAnimationController, onAnimationEnd: () -> Unit, ): Unit = coroutineScope { val iconAppearTranslation = configuration.getDimensionPixelSize(R.dimen.shelf_appear_translation).stateIn(this) val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW) viewModel.isVisible.collect { (isVisible, animate) -> viewModel.isVisible.collect { isVisible -> view.animate().cancel() val animatorListener = object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { isVisible.stopAnimating() } } when { !animate -> { !isVisible.isAnimating -> { view.alpha = 1f if (!statusViewMigrated) { view.translationY = 0f } view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE view.visibility = if (isVisible.value) View.VISIBLE else View.INVISIBLE } featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> { animateInIconTranslation(view, statusViewMigrated) if (isVisible) { CrossFadeHelper.fadeIn(view, onAnimationEnd) if (isVisible.value) { CrossFadeHelper.fadeIn(view, animatorListener) } else { CrossFadeHelper.fadeOut(view, onAnimationEnd) CrossFadeHelper.fadeOut(view, animatorListener) } } !isVisible -> { !isVisible.value -> { // Let's make sure the icon are translated to 0, since we cancelled it above animateInIconTranslation(view, statusViewMigrated) CrossFadeHelper.fadeOut(view, onAnimationEnd) CrossFadeHelper.fadeOut(view, animatorListener) } view.visibility != View.VISIBLE -> { // No fading here, let's just appear the icons instead! Loading @@ -262,14 +280,14 @@ object NotificationIconContainerViewBinder { animate = screenOffAnimationController.shouldAnimateAodIcons(), iconAppearTranslation.value, statusViewMigrated, animatorListener, ) onAnimationEnd() } else -> { // Let's make sure the icons are translated to 0, since we cancelled it above animateInIconTranslation(view, statusViewMigrated) // We were fading out, let's fade in instead CrossFadeHelper.fadeIn(view, onAnimationEnd) CrossFadeHelper.fadeIn(view, animatorListener) } } } Loading @@ -280,18 +298,20 @@ object NotificationIconContainerViewBinder { animate: Boolean, iconAppearTranslation: Int, statusViewMigrated: Boolean, animatorListener: Animator.AnimatorListener, ) { if (animate) { if (!statusViewMigrated) { view.translationY = -iconAppearTranslation.toFloat() } view.alpha = 0f animateInIconTranslation(view, statusViewMigrated) view .animate() .alpha(1f) .setInterpolator(Interpolators.LINEAR) .setDuration(AOD_ICONS_APPEAR_DURATION) .apply { if (statusViewMigrated) animateInIconTranslation() } .setListener(animatorListener) .start() } else { view.alpha = 1.0f Loading @@ -303,15 +323,13 @@ object NotificationIconContainerViewBinder { private fun animateInIconTranslation(view: View, statusViewMigrated: Boolean) { if (!statusViewMigrated) { view .animate() .setInterpolator(Interpolators.DECELERATE_QUINT) .translationY(0f) .setDuration(AOD_ICONS_APPEAR_DURATION) .start() view.animate().animateInIconTranslation().setDuration(AOD_ICONS_APPEAR_DURATION).start() } } private fun ViewPropertyAnimator.animateInIconTranslation(): ViewPropertyAnimator = setInterpolator(Interpolators.DECELERATE_QUINT).translationY(0f) private const val AOD_ICONS_APPEAR_DURATION: Long = 200 private val View.viewBounds: Rect Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt +24 −28 Original line number Diff line number Diff line Loading @@ -41,9 +41,9 @@ import com.android.systemui.util.kotlin.sample import com.android.systemui.util.ui.AnimatableEvent import com.android.systemui.util.ui.AnimatedValue import com.android.systemui.util.ui.toAnimatedValueFlow import com.android.systemui.util.ui.zip import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading @@ -65,9 +65,6 @@ constructor( shadeInteractor: ShadeInteractor, ) : NotificationIconContainerViewModel { private val onDozeAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1) private val onVisAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1) override val iconColors: Flow<ColorLookup> = configuration.getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR).map { tint -> ColorLookup { IconColorsImpl(tint) } Loading Loading @@ -96,7 +93,7 @@ constructor( AnimatableEvent(isDozing, animate) } .distinctUntilChanged() .toAnimatedValueFlow(completionEvents = onDozeAnimationComplete) .toAnimatedValueFlow() override val isVisible: Flow<AnimatedValue<Boolean>> = combine( Loading @@ -106,36 +103,35 @@ constructor( isPulseExpandingAnimated(), ) { onKeyguard: Boolean, bypassEnabled: Boolean, (notifsFullyHidden: Boolean, isAnimatingHide: Boolean), (pulseExpanding: Boolean, isAnimatingPulse: Boolean), isBypassEnabled: Boolean, notifsFullyHidden: AnimatedValue<Boolean>, pulseExpanding: AnimatedValue<Boolean>, -> val isAnimating = isAnimatingHide || isAnimatingPulse when { // Hide the AOD icons if we're not in the KEYGUARD state unless the screen off // animation is playing, in which case we want them to be visible if we're // animating in the AOD UI and will be switching to KEYGUARD shortly. !onKeyguard && !screenOffAnimationController.shouldShowAodIconsWhenShade() -> AnimatedValue(false, isAnimating = false) AnimatedValue.NotAnimating(false) else -> zip(notifsFullyHidden, pulseExpanding) { areNotifsFullyHidden, isPulseExpanding, -> when { // If we're bypassing, then we're visible bypassEnabled -> AnimatedValue(true, isAnimating) isBypassEnabled -> true // If we are pulsing (and not bypassing), then we are hidden pulseExpanding -> AnimatedValue(false, isAnimating) isPulseExpanding -> false // If notifs are fully gone, then we're visible notifsFullyHidden -> AnimatedValue(true, isAnimating) areNotifsFullyHidden -> true // Otherwise, we're hidden else -> AnimatedValue(false, isAnimating) else -> false } } .distinctUntilChanged() override fun completeDozeAnimation() { onDozeAnimationComplete.tryEmit(Unit) } override fun completeVisibilityAnimation() { onVisAnimationComplete.tryEmit(Unit) } .distinctUntilChanged() override val iconsViewData: Flow<IconsViewData> = iconsInteractor.aodNotifs.map { entries -> Loading @@ -150,7 +146,7 @@ constructor( .pairwise(initialValue = null) // If pulsing changes, start animating, unless it's the first emission .map { (prev, expanding) -> AnimatableEvent(expanding, startAnimating = prev != null) } .toAnimatedValueFlow(completionEvents = onVisAnimationComplete) .toAnimatedValueFlow() } /** Are notifications completely hidden from view, are we animating in response? */ Loading @@ -176,7 +172,7 @@ constructor( } AnimatableEvent(fullyHidden, animate) } .toAnimatedValueFlow(completionEvents = onVisAnimationComplete) .toAnimatedValueFlow() } private class IconColorsImpl(override val tint: Int) : IconColors { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt +1 −2 Original line number Diff line number Diff line Loading @@ -31,11 +31,10 @@ class NotificationIconContainerShelfViewModel constructor( interactor: NotificationIconsInteractor, ) : NotificationIconContainerViewModel { override val animationsEnabled: Flow<Boolean> = flowOf(true) override val isDozing: Flow<AnimatedValue<Boolean>> = emptyFlow() override val isVisible: Flow<AnimatedValue<Boolean>> = emptyFlow() override fun completeDozeAnimation() {} override fun completeVisibilityAnimation() {} override val iconColors: Flow<ColorLookup> = emptyFlow() override val iconsViewData: Flow<IconsViewData> = Loading Loading
packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java +1 −2 Original line number Diff line number Diff line Loading @@ -652,8 +652,7 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll CrossFadeHelper.fadeOut( mLayout, mFadeOutDuration, /* delay= */ 0, /* endRunnable= */ null); /* delay= */ 0); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java +64 −12 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.statusbar; import android.animation.Animator; import android.view.View; import android.view.ViewPropertyAnimator; import androidx.annotation.Nullable; Loading @@ -31,32 +33,58 @@ public class CrossFadeHelper { public static final long ANIMATION_DURATION_LENGTH = 210; public static void fadeOut(final View view) { fadeOut(view, null); fadeOut(view, (Runnable) null); } public static void fadeOut(final View view, final Runnable endRunnable) { fadeOut(view, ANIMATION_DURATION_LENGTH, 0, endRunnable); } public static void fadeOut(final View view, final Animator.AnimatorListener listener) { fadeOut(view, ANIMATION_DURATION_LENGTH, 0, listener); } public static void fadeOut(final View view, long duration, int delay) { fadeOut(view, duration, delay, (Runnable) null); } public static void fadeOut(final View view, long duration, int delay, final Runnable endRunnable) { @Nullable final Runnable endRunnable) { view.animate().cancel(); view.animate() .alpha(0f) .setDuration(duration) .setInterpolator(Interpolators.ALPHA_OUT) .setStartDelay(delay) .withEndAction(new Runnable() { @Override public void run() { .withEndAction(() -> { if (endRunnable != null) { endRunnable.run(); } if (view.getVisibility() != View.GONE) { view.setVisibility(View.INVISIBLE); } }); if (view.hasOverlappingRendering()) { view.animate().withLayer(); } } public static void fadeOut(final View view, long duration, int delay, @Nullable final Animator.AnimatorListener listener) { view.animate().cancel(); ViewPropertyAnimator animator = view.animate() .alpha(0f) .setDuration(duration) .setInterpolator(Interpolators.ALPHA_OUT) .setStartDelay(delay) .withEndAction(() -> { if (view.getVisibility() != View.GONE) { view.setVisibility(View.INVISIBLE); } }); if (listener != null) { animator.setListener(listener); } if (view.hasOverlappingRendering()) { view.animate().withLayer(); } Loading Loading @@ -119,8 +147,12 @@ public class CrossFadeHelper { fadeIn(view, ANIMATION_DURATION_LENGTH, /* delay= */ 0, endRunnable); } public static void fadeIn(final View view, Animator.AnimatorListener listener) { fadeIn(view, ANIMATION_DURATION_LENGTH, /* delay= */ 0, listener); } public static void fadeIn(final View view, long duration, int delay) { fadeIn(view, duration, delay, /* endRunnable= */ null); fadeIn(view, duration, delay, /* endRunnable= */ (Runnable) null); } public static void fadeIn(final View view, long duration, int delay, Loading @@ -141,6 +173,26 @@ public class CrossFadeHelper { } } public static void fadeIn(final View view, long duration, int delay, @Nullable Animator.AnimatorListener listener) { view.animate().cancel(); if (view.getVisibility() == View.INVISIBLE) { view.setAlpha(0.0f); view.setVisibility(View.VISIBLE); } ViewPropertyAnimator animator = view.animate() .alpha(1f) .setDuration(duration) .setStartDelay(delay) .setInterpolator(Interpolators.ALPHA_IN); if (listener != null) { animator.setListener(listener); } if (view.hasOverlappingRendering() && view.getLayerType() != View.LAYER_TYPE_HARDWARE) { view.animate().withLayer(); } } public static void fadeIn(View view, float fadeInAmount) { fadeIn(view, fadeInAmount, false /* remap */); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +45 −27 Original line number Diff line number Diff line Loading @@ -15,8 +15,11 @@ */ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.graphics.Rect import android.view.View import android.view.ViewPropertyAnimator import android.widget.FrameLayout import androidx.collection.ArrayMap import androidx.lifecycle.Lifecycle Loading Loading @@ -46,6 +49,9 @@ import com.android.systemui.util.children import com.android.systemui.util.kotlin.mapValuesNotNullTo import com.android.systemui.util.kotlin.sample import com.android.systemui.util.kotlin.stateFlow import com.android.systemui.util.ui.isAnimating import com.android.systemui.util.ui.stopAnimating import com.android.systemui.util.ui.value import javax.inject.Inject import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.coroutineScope Loading Loading @@ -73,16 +79,24 @@ object NotificationIconContainerViewBinder { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) } launch { viewModel.isDozing.collect { (isDozing, animate) -> val animateIfNotBlanking = animate && !dozeParameters.displayNeedsBlanking viewModel.isDozing.collect { isDozing -> if (isDozing.isAnimating) { val animate = !dozeParameters.displayNeedsBlanking view.setDozing( /* dozing = */ isDozing, /* fade = */ animateIfNotBlanking, /* dozing = */ isDozing.value, /* fade = */ animate, /* delay = */ 0, /* endRunnable = */ isDozing::stopAnimating, ) } else { view.setDozing( /* dozing = */ isDozing.value, /* fade= */ false, /* delay= */ 0, /* endRunnable = */ viewModel::completeDozeAnimation, ) } } } // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC // view-binder launch { Loading @@ -92,7 +106,6 @@ object NotificationIconContainerViewBinder { configuration, featureFlags, screenOffAnimationController, onAnimationEnd = viewModel::completeVisibilityAnimation, ) } launch { Loading Loading @@ -225,33 +238,38 @@ object NotificationIconContainerViewBinder { configuration: ConfigurationState, featureFlags: FeatureFlagsClassic, screenOffAnimationController: ScreenOffAnimationController, onAnimationEnd: () -> Unit, ): Unit = coroutineScope { val iconAppearTranslation = configuration.getDimensionPixelSize(R.dimen.shelf_appear_translation).stateIn(this) val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW) viewModel.isVisible.collect { (isVisible, animate) -> viewModel.isVisible.collect { isVisible -> view.animate().cancel() val animatorListener = object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { isVisible.stopAnimating() } } when { !animate -> { !isVisible.isAnimating -> { view.alpha = 1f if (!statusViewMigrated) { view.translationY = 0f } view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE view.visibility = if (isVisible.value) View.VISIBLE else View.INVISIBLE } featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> { animateInIconTranslation(view, statusViewMigrated) if (isVisible) { CrossFadeHelper.fadeIn(view, onAnimationEnd) if (isVisible.value) { CrossFadeHelper.fadeIn(view, animatorListener) } else { CrossFadeHelper.fadeOut(view, onAnimationEnd) CrossFadeHelper.fadeOut(view, animatorListener) } } !isVisible -> { !isVisible.value -> { // Let's make sure the icon are translated to 0, since we cancelled it above animateInIconTranslation(view, statusViewMigrated) CrossFadeHelper.fadeOut(view, onAnimationEnd) CrossFadeHelper.fadeOut(view, animatorListener) } view.visibility != View.VISIBLE -> { // No fading here, let's just appear the icons instead! Loading @@ -262,14 +280,14 @@ object NotificationIconContainerViewBinder { animate = screenOffAnimationController.shouldAnimateAodIcons(), iconAppearTranslation.value, statusViewMigrated, animatorListener, ) onAnimationEnd() } else -> { // Let's make sure the icons are translated to 0, since we cancelled it above animateInIconTranslation(view, statusViewMigrated) // We were fading out, let's fade in instead CrossFadeHelper.fadeIn(view, onAnimationEnd) CrossFadeHelper.fadeIn(view, animatorListener) } } } Loading @@ -280,18 +298,20 @@ object NotificationIconContainerViewBinder { animate: Boolean, iconAppearTranslation: Int, statusViewMigrated: Boolean, animatorListener: Animator.AnimatorListener, ) { if (animate) { if (!statusViewMigrated) { view.translationY = -iconAppearTranslation.toFloat() } view.alpha = 0f animateInIconTranslation(view, statusViewMigrated) view .animate() .alpha(1f) .setInterpolator(Interpolators.LINEAR) .setDuration(AOD_ICONS_APPEAR_DURATION) .apply { if (statusViewMigrated) animateInIconTranslation() } .setListener(animatorListener) .start() } else { view.alpha = 1.0f Loading @@ -303,15 +323,13 @@ object NotificationIconContainerViewBinder { private fun animateInIconTranslation(view: View, statusViewMigrated: Boolean) { if (!statusViewMigrated) { view .animate() .setInterpolator(Interpolators.DECELERATE_QUINT) .translationY(0f) .setDuration(AOD_ICONS_APPEAR_DURATION) .start() view.animate().animateInIconTranslation().setDuration(AOD_ICONS_APPEAR_DURATION).start() } } private fun ViewPropertyAnimator.animateInIconTranslation(): ViewPropertyAnimator = setInterpolator(Interpolators.DECELERATE_QUINT).translationY(0f) private const val AOD_ICONS_APPEAR_DURATION: Long = 200 private val View.viewBounds: Rect Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt +24 −28 Original line number Diff line number Diff line Loading @@ -41,9 +41,9 @@ import com.android.systemui.util.kotlin.sample import com.android.systemui.util.ui.AnimatableEvent import com.android.systemui.util.ui.AnimatedValue import com.android.systemui.util.ui.toAnimatedValueFlow import com.android.systemui.util.ui.zip import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading @@ -65,9 +65,6 @@ constructor( shadeInteractor: ShadeInteractor, ) : NotificationIconContainerViewModel { private val onDozeAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1) private val onVisAnimationComplete = MutableSharedFlow<Unit>(extraBufferCapacity = 1) override val iconColors: Flow<ColorLookup> = configuration.getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR).map { tint -> ColorLookup { IconColorsImpl(tint) } Loading Loading @@ -96,7 +93,7 @@ constructor( AnimatableEvent(isDozing, animate) } .distinctUntilChanged() .toAnimatedValueFlow(completionEvents = onDozeAnimationComplete) .toAnimatedValueFlow() override val isVisible: Flow<AnimatedValue<Boolean>> = combine( Loading @@ -106,36 +103,35 @@ constructor( isPulseExpandingAnimated(), ) { onKeyguard: Boolean, bypassEnabled: Boolean, (notifsFullyHidden: Boolean, isAnimatingHide: Boolean), (pulseExpanding: Boolean, isAnimatingPulse: Boolean), isBypassEnabled: Boolean, notifsFullyHidden: AnimatedValue<Boolean>, pulseExpanding: AnimatedValue<Boolean>, -> val isAnimating = isAnimatingHide || isAnimatingPulse when { // Hide the AOD icons if we're not in the KEYGUARD state unless the screen off // animation is playing, in which case we want them to be visible if we're // animating in the AOD UI and will be switching to KEYGUARD shortly. !onKeyguard && !screenOffAnimationController.shouldShowAodIconsWhenShade() -> AnimatedValue(false, isAnimating = false) AnimatedValue.NotAnimating(false) else -> zip(notifsFullyHidden, pulseExpanding) { areNotifsFullyHidden, isPulseExpanding, -> when { // If we're bypassing, then we're visible bypassEnabled -> AnimatedValue(true, isAnimating) isBypassEnabled -> true // If we are pulsing (and not bypassing), then we are hidden pulseExpanding -> AnimatedValue(false, isAnimating) isPulseExpanding -> false // If notifs are fully gone, then we're visible notifsFullyHidden -> AnimatedValue(true, isAnimating) areNotifsFullyHidden -> true // Otherwise, we're hidden else -> AnimatedValue(false, isAnimating) else -> false } } .distinctUntilChanged() override fun completeDozeAnimation() { onDozeAnimationComplete.tryEmit(Unit) } override fun completeVisibilityAnimation() { onVisAnimationComplete.tryEmit(Unit) } .distinctUntilChanged() override val iconsViewData: Flow<IconsViewData> = iconsInteractor.aodNotifs.map { entries -> Loading @@ -150,7 +146,7 @@ constructor( .pairwise(initialValue = null) // If pulsing changes, start animating, unless it's the first emission .map { (prev, expanding) -> AnimatableEvent(expanding, startAnimating = prev != null) } .toAnimatedValueFlow(completionEvents = onVisAnimationComplete) .toAnimatedValueFlow() } /** Are notifications completely hidden from view, are we animating in response? */ Loading @@ -176,7 +172,7 @@ constructor( } AnimatableEvent(fullyHidden, animate) } .toAnimatedValueFlow(completionEvents = onVisAnimationComplete) .toAnimatedValueFlow() } private class IconColorsImpl(override val tint: Int) : IconColors { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt +1 −2 Original line number Diff line number Diff line Loading @@ -31,11 +31,10 @@ class NotificationIconContainerShelfViewModel constructor( interactor: NotificationIconsInteractor, ) : NotificationIconContainerViewModel { override val animationsEnabled: Flow<Boolean> = flowOf(true) override val isDozing: Flow<AnimatedValue<Boolean>> = emptyFlow() override val isVisible: Flow<AnimatedValue<Boolean>> = emptyFlow() override fun completeDozeAnimation() {} override fun completeVisibilityAnimation() {} override val iconColors: Flow<ColorLookup> = emptyFlow() override val iconsViewData: Flow<IconsViewData> = Loading