1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.phone.fragment 18 19 import android.content.res.Resources 20 import android.view.View 21 import androidx.core.animation.Animator 22 import androidx.core.animation.AnimatorSet 23 import androidx.core.animation.ValueAnimator 24 import com.android.systemui.res.R 25 import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN 26 import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT 27 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback 28 import com.android.systemui.util.animation.AnimationUtil.Companion.frames 29 import com.android.systemui.util.doOnCancel 30 import com.android.systemui.util.doOnEnd 31 32 /** 33 * An implementation of [StatusBarSystemEventDefaultAnimator], applying the onAlphaChanged and 34 * onTranslationXChanged callbacks directly to the provided animatedView. 35 */ 36 class StatusBarSystemEventAnimator 37 @JvmOverloads 38 constructor(val animatedView: View, resources: Resources, isAnimationRunning: Boolean = false) : 39 StatusBarSystemEventDefaultAnimator( 40 resources = resources, 41 onAlphaChanged = animatedView::setAlpha, 42 onTranslationXChanged = animatedView::setTranslationX, 43 isAnimationRunning = isAnimationRunning, 44 ) 45 46 /** 47 * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed 48 * status bar fragment), can use this Animator to get the default system status animation. It simply 49 * needs to implement the onAlphaChanged and onTranslationXChanged callbacks. 50 * 51 * This animator relies on resources, and should be recreated whenever resources are updated. While 52 * this class could be used directly as the animation callback, it's probably best to forward calls 53 * to it so that it can be recreated at any moment without needing to remove/add callback. 54 */ 55 open class StatusBarSystemEventDefaultAnimator 56 @JvmOverloads 57 constructor( 58 resources: Resources, 59 private val onAlphaChanged: (Float) -> Unit, 60 private val onTranslationXChanged: (Float) -> Unit, 61 var isAnimationRunning: Boolean = false, 62 ) : SystemStatusAnimationCallback { 63 private val translationXIn: Int = 64 resources.getDimensionPixelSize( 65 R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x 66 ) 67 private val translationXOut: Int = 68 resources.getDimensionPixelSize( 69 R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x 70 ) 71 onSystemEventAnimationBeginnull72 override fun onSystemEventAnimationBegin(): Animator { 73 isAnimationRunning = true 74 return getDefaultStatusBarAnimationForChipEnter( 75 translationXIn, 76 onTranslationXChanged, 77 onAlphaChanged, 78 ) 79 } 80 onSystemEventAnimationFinishnull81 override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { 82 onTranslationXChanged(translationXOut.toFloat()) 83 val anim = 84 getDefaultStatusBarAnimationForChipExit( 85 translationXOut, 86 onTranslationXChanged, 87 onAlphaChanged, 88 ) 89 anim.doOnEnd { isAnimationRunning = false } 90 anim.doOnCancel { isAnimationRunning = false } 91 92 return anim 93 } 94 95 /** Static definition of these animations so we can use them more easily from view binders */ 96 companion object { 97 /** 98 * Chip: coming in. Animated view: going out. 99 * 100 * Implements the exact spec for animating any status bar elements OUT to make space for the 101 * chip IN animation. 102 */ getDefaultStatusBarAnimationForChipEnternull103 fun getDefaultStatusBarAnimationForChipEnter( 104 targetTranslation: Int, 105 setX: (Float) -> Unit, 106 setAlpha: (Float) -> Unit, 107 ): Animator { 108 val moveOut = 109 ValueAnimator.ofFloat(0f, 1f).apply { 110 duration = 23.frames 111 interpolator = STATUS_BAR_X_MOVE_OUT 112 addUpdateListener { setX(-(targetTranslation * animatedValue as Float)) } 113 } 114 val alphaOut = 115 ValueAnimator.ofFloat(1f, 0f).apply { 116 duration = 8.frames 117 interpolator = null 118 addUpdateListener { setAlpha(animatedValue as Float) } 119 } 120 121 val animSet = AnimatorSet() 122 animSet.playTogether(moveOut, alphaOut) 123 return animSet 124 } 125 126 /** 127 * Chip: going out. Animated view: coming in. 128 * 129 * Implements the exact spec for animating any status bar elements IN as the chip is 130 * animating OUT 131 */ getDefaultStatusBarAnimationForChipExitnull132 fun getDefaultStatusBarAnimationForChipExit( 133 targetTranslation: Int, 134 setX: (Float) -> Unit, 135 setAlpha: (Float) -> Unit, 136 ): Animator { 137 val moveIn = 138 ValueAnimator.ofFloat(1f, 0f).apply { 139 duration = 23.frames 140 startDelay = 7.frames 141 interpolator = STATUS_BAR_X_MOVE_IN 142 addUpdateListener { setX(targetTranslation * animatedValue as Float) } 143 } 144 val alphaIn = 145 ValueAnimator.ofFloat(0f, 1f).apply { 146 duration = 5.frames 147 startDelay = 11.frames 148 interpolator = null 149 addUpdateListener { setAlpha(animatedValue as Float) } 150 } 151 152 val animatorSet = AnimatorSet() 153 animatorSet.playTogether(moveIn, alphaIn) 154 return animatorSet 155 } 156 } 157 } 158