/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.temporarydisplay.chipbar import android.view.View import android.view.ViewGroup import com.android.app.animation.Interpolators import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.children import javax.inject.Inject /** * A class controlling chipbar animations. Typically delegates to [ViewHierarchyAnimator]. * * Used so that animations can be mocked out in tests. */ @SysUISingleton open class ChipbarAnimator @Inject constructor() { /** * Animates [innerView] and its children into view. * * @return true if the animation was successfully started and false if the animation can't be * run for any reason. * * See [ViewHierarchyAnimator.animateAddition]. */ open fun animateViewIn(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean { return ViewHierarchyAnimator.animateAddition( innerView, ViewHierarchyAnimator.Hotspot.TOP, Interpolators.EMPHASIZED_DECELERATE, duration = ANIMATION_IN_DURATION, includeMargins = true, includeFadeIn = true, onAnimationEnd = onAnimationEnd, ) } /** * Animates [innerView] and its children out of view. * * @return true if the animation was successfully started and false if the animation can't be * run for any reason. * * See [ViewHierarchyAnimator.animateRemoval]. */ open fun animateViewOut(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean { return ViewHierarchyAnimator.animateRemoval( innerView, ViewHierarchyAnimator.Hotspot.TOP, Interpolators.EMPHASIZED_ACCELERATE, ANIMATION_OUT_DURATION, includeMargins = true, onAnimationEnd, ) } /** Force shows this view and all child views. Should be used in case [animateViewIn] fails. */ fun forceDisplayView(innerView: View) { innerView.alpha = 1f if (innerView is ViewGroup) { innerView.children.forEach { forceDisplayView(it) } } } } private const val ANIMATION_IN_DURATION = 500L private const val ANIMATION_OUT_DURATION = 250L