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.unfold.progress 17 18 import android.animation.Animator 19 import android.animation.ObjectAnimator 20 import android.util.FloatProperty 21 import com.android.systemui.unfold.UnfoldTransitionProgressProvider 22 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener 23 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED 24 import com.android.systemui.unfold.updates.FoldStateProvider 25 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate 26 import javax.inject.Inject 27 28 /** Emits animation progress with fixed timing after unfolding */ 29 internal class FixedTimingTransitionProgressProvider 30 @Inject 31 constructor(private val foldStateProvider: FoldStateProvider) : 32 UnfoldTransitionProgressProvider, FoldStateProvider.FoldUpdatesListener { 33 34 private val animatorListener = AnimatorListener() 35 private val animator = <lambda>null36 ObjectAnimator.ofFloat(this, AnimationProgressProperty, 0f, 1f).apply { 37 duration = TRANSITION_TIME_MILLIS 38 addListener(animatorListener) 39 } 40 41 private var transitionProgress: Float = 0.0f 42 set(value) { <lambda>null43 listeners.forEach { it.onTransitionProgress(value) } 44 field = value 45 } 46 47 private val listeners: MutableList<TransitionProgressListener> = mutableListOf() 48 49 init { 50 foldStateProvider.addCallback(this) 51 foldStateProvider.start() 52 } 53 destroynull54 override fun destroy() { 55 animator.cancel() 56 foldStateProvider.removeCallback(this) 57 foldStateProvider.stop() 58 } 59 onFoldUpdatenull60 override fun onFoldUpdate(@FoldUpdate update: Int) { 61 if (update == FOLD_UPDATE_FINISH_CLOSED) { 62 animator.cancel() 63 } 64 } 65 onUnfoldedScreenAvailablenull66 override fun onUnfoldedScreenAvailable() { 67 animator.start() 68 } 69 addCallbacknull70 override fun addCallback(listener: TransitionProgressListener) { 71 listeners.add(listener) 72 } 73 removeCallbacknull74 override fun removeCallback(listener: TransitionProgressListener) { 75 listeners.remove(listener) 76 } 77 78 private object AnimationProgressProperty : 79 FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") { 80 setValuenull81 override fun setValue(provider: FixedTimingTransitionProgressProvider, value: Float) { 82 provider.transitionProgress = value 83 } 84 getnull85 override fun get(provider: FixedTimingTransitionProgressProvider): Float = 86 provider.transitionProgress 87 } 88 89 private inner class AnimatorListener : Animator.AnimatorListener { 90 91 override fun onAnimationStart(animator: Animator) { 92 listeners.forEach { it.onTransitionStarted() } 93 listeners.forEach { it.onTransitionFinishing() } 94 } 95 96 override fun onAnimationEnd(animator: Animator) { 97 listeners.forEach { it.onTransitionFinished() } 98 } 99 100 override fun onAnimationRepeat(animator: Animator) {} 101 102 override fun onAnimationCancel(animator: Animator) {} 103 } 104 105 private companion object { 106 private const val TRANSITION_TIME_MILLIS = 400L 107 } 108 } 109