Loading packages/SystemUI/animation/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ <!-- ViewBoundsAnimator --> <item type="id" name="tag_animator"/> <item type="id" name="tag_alpha_animator"/> <item type="id" name="tag_layout_listener"/> <item type="id" name="tag_override_bottom"/> <item type="id" name="tag_override_left"/> Loading packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt +65 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class ViewHierarchyAnimator { private val DEFAULT_INTERPOLATOR = Interpolators.STANDARD private val DEFAULT_ADDITION_INTERPOLATOR = Interpolators.STANDARD_DECELERATE private val DEFAULT_REMOVAL_INTERPOLATOR = Interpolators.STANDARD_ACCELERATE private val DEFAULT_FADE_IN_INTERPOLATOR = Interpolators.ALPHA_IN /** The properties used to animate the view bounds. */ private val PROPERTIES = mapOf( Loading Loading @@ -162,6 +163,10 @@ class ViewHierarchyAnimator { * animate an already visible view, see [animate] and [animateNextUpdate]. * * Then animator unregisters itself once the first addition animation is complete. * * @param includeFadeIn true if the animator should also fade in the view and child views. * @param fadeInInterpolator the interpolator to use when fading in the view. Unused if * [includeFadeIn] is false. */ @JvmOverloads fun animateAddition( Loading @@ -169,7 +174,9 @@ class ViewHierarchyAnimator { origin: Hotspot = Hotspot.CENTER, interpolator: Interpolator = DEFAULT_ADDITION_INTERPOLATOR, duration: Long = DEFAULT_DURATION, includeMargins: Boolean = false includeMargins: Boolean = false, includeFadeIn: Boolean = false, fadeInInterpolator: Interpolator = DEFAULT_FADE_IN_INTERPOLATOR ): Boolean { if (isVisible( rootView.visibility, Loading @@ -186,6 +193,42 @@ class ViewHierarchyAnimator { origin, interpolator, duration, ignorePreviousValues = !includeMargins ) addListener(rootView, listener, recursive = true) if (!includeFadeIn) { return true } if (rootView is ViewGroup) { // First, fade in the container view val containerDuration = duration / 6 createAndStartFadeInAnimator( rootView, containerDuration, startDelay = 0, interpolator = fadeInInterpolator ) // Then, fade in the child views val childDuration = duration / 3 for (i in 0 until rootView.childCount) { val view = rootView.getChildAt(i) createAndStartFadeInAnimator( view, childDuration, // Wait until the container fades in before fading in the children startDelay = containerDuration, interpolator = fadeInInterpolator ) } // For now, we don't recursively fade in additional sub views (e.g. grandchild // views) since it hasn't been necessary, but we could add that functionality. } else { // Fade in the view during the first half of the addition createAndStartFadeInAnimator( rootView, duration / 2, startDelay = 0, interpolator = fadeInInterpolator ) } return true } Loading Loading @@ -834,6 +877,27 @@ class ViewHierarchyAnimator { view.setTag(R.id.tag_animator, animator) animator.start() } private fun createAndStartFadeInAnimator( view: View, duration: Long, startDelay: Long, interpolator: Interpolator ) { val animator = ObjectAnimator.ofFloat(view, "alpha", 1f) animator.startDelay = startDelay animator.duration = duration animator.interpolator = interpolator animator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { view.setTag(R.id.tag_alpha_animator, null /* tag */) } }) (view.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.cancel() view.setTag(R.id.tag_alpha_animator, animator) animator.start() } } /** An enum used to determine the origin of addition animations. */ Loading packages/SystemUI/res/layout/media_ttt_chip.xml +70 −56 Original line number Diff line number Diff line Loading @@ -13,18 +13,27 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout <!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view is the root view of a window, we cannot change the root view's margins.) --> <!-- Alphas start as 0 because the view will be animated in. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/media_ttt_sender_chip" android:layout_width="wrap_content" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/media_ttt_sender_chip_inner" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/media_ttt_chip_outer_padding" android:background="@drawable/media_ttt_chip_background" android:layout_marginTop="50dp" android:layout_marginTop="20dp" android:clipToPadding="false" android:gravity="center_vertical" android:alpha="0.0" > <com.android.internal.widget.CachingIconView Loading @@ -32,6 +41,7 @@ android:layout_width="@dimen/media_ttt_app_icon_size" android:layout_height="@dimen/media_ttt_app_icon_size" android:layout_marginEnd="12dp" android:alpha="0.0" /> <TextView Loading @@ -40,10 +50,10 @@ android:layout_height="wrap_content" android:textSize="@dimen/media_ttt_text_size" android:textColor="?android:attr/textColorPrimary" android:alpha="0.0" /> <!-- At most one of [loading, failure_icon, undo] will be visible at a time. --> <ProgressBar android:id="@+id/loading" android:indeterminate="true" Loading @@ -52,6 +62,7 @@ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant" style="?android:attr/progressBarStyleSmall" android:alpha="0.0" /> <ImageView Loading @@ -61,6 +72,7 @@ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" android:src="@drawable/ic_warning" android:tint="@color/GM2_red_500" android:alpha="0.0" /> <TextView Loading @@ -78,6 +90,8 @@ android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin" android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin" android:background="@drawable/media_ttt_undo_background" android:alpha="0.0" /> </LinearLayout> </FrameLayout> packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +7 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( PowerManager.WAKE_REASON_APPLICATION, "com.android.systemui:media_tap_to_transfer_activated" ) animateChipIn(currentChipView) } // Cancel and re-set the chip timeout each time we get a new state. Loading Loading @@ -137,6 +138,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( */ abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup) /** * A method that can be implemented by subclcasses to do custom animations for when the chip * appears. */ open fun animateChipIn(chipView: ViewGroup) {} /** * Returns the size that the icon should be, or null if no size override is needed. */ Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +13 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.view.WindowManager import android.widget.TextView import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.ChipInfoCommon Loading Loading @@ -124,7 +126,6 @@ class MediaTttChipControllerSender @Inject constructor( currentChipView.requireViewById<View>(R.id.loading).visibility = chipState.isMidTransfer.visibleIfTrue() // Undo val undoView = currentChipView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( Loading @@ -138,6 +139,17 @@ class MediaTttChipControllerSender @Inject constructor( chipState.isTransferFailure.visibleIfTrue() } override fun animateChipIn(chipView: ViewGroup) { ViewHierarchyAnimator.animateAddition( chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner), ViewHierarchyAnimator.Hotspot.TOP, Interpolators.EMPHASIZED_DECELERATE, duration = 500L, includeMargins = true, includeFadeIn = true, ) } override fun removeChip(removalReason: String) { // Don't remove the chip if we're mid-transfer since the user should still be able to // see the status of the transfer. (But do remove it if it's finally timed out.) Loading Loading
packages/SystemUI/animation/res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ <!-- ViewBoundsAnimator --> <item type="id" name="tag_animator"/> <item type="id" name="tag_alpha_animator"/> <item type="id" name="tag_layout_listener"/> <item type="id" name="tag_override_bottom"/> <item type="id" name="tag_override_left"/> Loading
packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt +65 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class ViewHierarchyAnimator { private val DEFAULT_INTERPOLATOR = Interpolators.STANDARD private val DEFAULT_ADDITION_INTERPOLATOR = Interpolators.STANDARD_DECELERATE private val DEFAULT_REMOVAL_INTERPOLATOR = Interpolators.STANDARD_ACCELERATE private val DEFAULT_FADE_IN_INTERPOLATOR = Interpolators.ALPHA_IN /** The properties used to animate the view bounds. */ private val PROPERTIES = mapOf( Loading Loading @@ -162,6 +163,10 @@ class ViewHierarchyAnimator { * animate an already visible view, see [animate] and [animateNextUpdate]. * * Then animator unregisters itself once the first addition animation is complete. * * @param includeFadeIn true if the animator should also fade in the view and child views. * @param fadeInInterpolator the interpolator to use when fading in the view. Unused if * [includeFadeIn] is false. */ @JvmOverloads fun animateAddition( Loading @@ -169,7 +174,9 @@ class ViewHierarchyAnimator { origin: Hotspot = Hotspot.CENTER, interpolator: Interpolator = DEFAULT_ADDITION_INTERPOLATOR, duration: Long = DEFAULT_DURATION, includeMargins: Boolean = false includeMargins: Boolean = false, includeFadeIn: Boolean = false, fadeInInterpolator: Interpolator = DEFAULT_FADE_IN_INTERPOLATOR ): Boolean { if (isVisible( rootView.visibility, Loading @@ -186,6 +193,42 @@ class ViewHierarchyAnimator { origin, interpolator, duration, ignorePreviousValues = !includeMargins ) addListener(rootView, listener, recursive = true) if (!includeFadeIn) { return true } if (rootView is ViewGroup) { // First, fade in the container view val containerDuration = duration / 6 createAndStartFadeInAnimator( rootView, containerDuration, startDelay = 0, interpolator = fadeInInterpolator ) // Then, fade in the child views val childDuration = duration / 3 for (i in 0 until rootView.childCount) { val view = rootView.getChildAt(i) createAndStartFadeInAnimator( view, childDuration, // Wait until the container fades in before fading in the children startDelay = containerDuration, interpolator = fadeInInterpolator ) } // For now, we don't recursively fade in additional sub views (e.g. grandchild // views) since it hasn't been necessary, but we could add that functionality. } else { // Fade in the view during the first half of the addition createAndStartFadeInAnimator( rootView, duration / 2, startDelay = 0, interpolator = fadeInInterpolator ) } return true } Loading Loading @@ -834,6 +877,27 @@ class ViewHierarchyAnimator { view.setTag(R.id.tag_animator, animator) animator.start() } private fun createAndStartFadeInAnimator( view: View, duration: Long, startDelay: Long, interpolator: Interpolator ) { val animator = ObjectAnimator.ofFloat(view, "alpha", 1f) animator.startDelay = startDelay animator.duration = duration animator.interpolator = interpolator animator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { view.setTag(R.id.tag_alpha_animator, null /* tag */) } }) (view.getTag(R.id.tag_alpha_animator) as? ObjectAnimator)?.cancel() view.setTag(R.id.tag_alpha_animator, animator) animator.start() } } /** An enum used to determine the origin of addition animations. */ Loading
packages/SystemUI/res/layout/media_ttt_chip.xml +70 −56 Original line number Diff line number Diff line Loading @@ -13,18 +13,27 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout <!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view is the root view of a window, we cannot change the root view's margins.) --> <!-- Alphas start as 0 because the view will be animated in. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:id="@+id/media_ttt_sender_chip" android:layout_width="wrap_content" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/media_ttt_sender_chip_inner" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/media_ttt_chip_outer_padding" android:background="@drawable/media_ttt_chip_background" android:layout_marginTop="50dp" android:layout_marginTop="20dp" android:clipToPadding="false" android:gravity="center_vertical" android:alpha="0.0" > <com.android.internal.widget.CachingIconView Loading @@ -32,6 +41,7 @@ android:layout_width="@dimen/media_ttt_app_icon_size" android:layout_height="@dimen/media_ttt_app_icon_size" android:layout_marginEnd="12dp" android:alpha="0.0" /> <TextView Loading @@ -40,10 +50,10 @@ android:layout_height="wrap_content" android:textSize="@dimen/media_ttt_text_size" android:textColor="?android:attr/textColorPrimary" android:alpha="0.0" /> <!-- At most one of [loading, failure_icon, undo] will be visible at a time. --> <ProgressBar android:id="@+id/loading" android:indeterminate="true" Loading @@ -52,6 +62,7 @@ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant" style="?android:attr/progressBarStyleSmall" android:alpha="0.0" /> <ImageView Loading @@ -61,6 +72,7 @@ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin" android:src="@drawable/ic_warning" android:tint="@color/GM2_red_500" android:alpha="0.0" /> <TextView Loading @@ -78,6 +90,8 @@ android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin" android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin" android:background="@drawable/media_ttt_undo_background" android:alpha="0.0" /> </LinearLayout> </FrameLayout>
packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +7 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( PowerManager.WAKE_REASON_APPLICATION, "com.android.systemui:media_tap_to_transfer_activated" ) animateChipIn(currentChipView) } // Cancel and re-set the chip timeout each time we get a new state. Loading Loading @@ -137,6 +138,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( */ abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup) /** * A method that can be implemented by subclcasses to do custom animations for when the chip * appears. */ open fun animateChipIn(chipView: ViewGroup) {} /** * Returns the size that the icon should be, or null if no size override is needed. */ Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +13 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.view.WindowManager import android.widget.TextView import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.taptotransfer.common.ChipInfoCommon Loading Loading @@ -124,7 +126,6 @@ class MediaTttChipControllerSender @Inject constructor( currentChipView.requireViewById<View>(R.id.loading).visibility = chipState.isMidTransfer.visibleIfTrue() // Undo val undoView = currentChipView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( Loading @@ -138,6 +139,17 @@ class MediaTttChipControllerSender @Inject constructor( chipState.isTransferFailure.visibleIfTrue() } override fun animateChipIn(chipView: ViewGroup) { ViewHierarchyAnimator.animateAddition( chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner), ViewHierarchyAnimator.Hotspot.TOP, Interpolators.EMPHASIZED_DECELERATE, duration = 500L, includeMargins = true, includeFadeIn = true, ) } override fun removeChip(removalReason: String) { // Don't remove the chip if we're mid-transfer since the user should still be able to // see the status of the transfer. (But do remove it if it's finally timed out.) Loading