1 /* 2 * Copyright (C) 2021 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 package com.android.systemui.statusbar.phone 17 18 import android.view.View 19 import android.view.WindowManager 20 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator 21 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.AlphaProvider 22 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController.StatusBarViewsCenterProvider 23 import com.android.systemui.unfold.SysUIUnfoldScope 24 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener 25 import com.android.systemui.unfold.util.CurrentActivityTypeProvider 26 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider 27 import javax.inject.Inject 28 import kotlin.math.max 29 30 @SysUIUnfoldScope 31 class StatusBarMoveFromCenterAnimationController @Inject constructor( 32 private val progressProvider: ScopedUnfoldTransitionProgressProvider, 33 private val currentActivityTypeProvider: CurrentActivityTypeProvider, 34 windowManager: WindowManager 35 ) { 36 37 // Whether we're on home activity. Updated only when the animation starts. 38 private var isOnHomeActivity: Boolean? = null 39 40 private val transitionListener = TransitionListener() 41 private val moveFromCenterAnimator = UnfoldMoveFromCenterAnimator( 42 windowManager, 43 viewCenterProvider = StatusBarViewsCenterProvider(), 44 alphaProvider = StatusBarIconsAlphaProvider() 45 ) 46 onViewsReadynull47 fun onViewsReady(viewsToAnimate: Array<View>) { 48 moveFromCenterAnimator.updateDisplayProperties() 49 50 viewsToAnimate.forEach { 51 moveFromCenterAnimator.registerViewForAnimation(it) 52 } 53 54 progressProvider.addCallback(transitionListener) 55 } 56 onViewDetachednull57 fun onViewDetached() { 58 progressProvider.removeCallback(transitionListener) 59 moveFromCenterAnimator.clearRegisteredViews() 60 } 61 onStatusBarWidthChangednull62 fun onStatusBarWidthChanged() { 63 moveFromCenterAnimator.updateDisplayProperties() 64 moveFromCenterAnimator.updateViewPositions() 65 } 66 67 private inner class TransitionListener : TransitionProgressListener { onTransitionStartednull68 override fun onTransitionStarted() { 69 isOnHomeActivity = currentActivityTypeProvider.isHomeActivity 70 } 71 onTransitionProgressnull72 override fun onTransitionProgress(progress: Float) { 73 moveFromCenterAnimator.onTransitionProgress(progress) 74 } 75 onTransitionFinishednull76 override fun onTransitionFinished() { 77 // Reset translations when transition is stopped/cancelled 78 // (e.g. the transition could be cancelled mid-way when rotating the screen) 79 moveFromCenterAnimator.onTransitionProgress(1f) 80 isOnHomeActivity = null 81 } 82 } 83 84 85 /** 86 * In certain cases, an alpha is applied based on the progress. 87 * 88 * This mainly happens to hide the statusbar during the unfold animation while on apps, as the 89 * bounds of the app "collapse" to the center, but the statusbar doesn't. 90 * While on launcher, this alpha is not applied. 91 */ 92 private inner class StatusBarIconsAlphaProvider : AlphaProvider { getAlphanull93 override fun getAlpha(progress: Float): Float { 94 if (isOnHomeActivity == true) { 95 return 1.0f 96 } 97 return max( 98 0f, 99 (progress - ICONS_START_APPEARING_PROGRESS) / (1 - ICONS_START_APPEARING_PROGRESS) 100 ) 101 } 102 } 103 } 104 105 private const val ICONS_START_APPEARING_PROGRESS = 0.75F 106