/* * 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.intentresolver import android.view.View import android.view.animation.AlphaAnimation import android.view.animation.LinearInterpolator import android.view.animation.Transformation import com.android.intentresolver.chooser.TargetInfo private const val IMAGE_FADE_IN_MILLIS = 150L internal class ItemRevealAnimationTracker { private val iconProgress = HashMap() private val labelProgress = HashMap() fun reset() { iconProgress.clear() labelProgress.clear() } fun animateIcon(view: View, info: TargetInfo) = animateView(view, info, iconProgress) fun animateLabel(view: View, info: TargetInfo) = animateView(view, info, labelProgress) private fun animateView(view: View, info: TargetInfo, map: MutableMap) { val record = map.getOrPut(info) { Record() } if ((view.animation as? RevealAnimation)?.record === record) return view.clearAnimation() if (record.alpha >= 1f) { view.alpha = 1f return } view.startAnimation(RevealAnimation(record)) } private class Record(var alpha: Float = 0f) private class RevealAnimation(val record: Record) : AlphaAnimation(record.alpha, 1f) { init { duration = (IMAGE_FADE_IN_MILLIS * (1f - record.alpha)).toLong() interpolator = LinearInterpolator() } override fun applyTransformation(interpolatedTime: Float, t: Transformation) { super.applyTransformation(interpolatedTime, t) // One TargetInfo can be simultaneously bou into multiple UI grid items; make sure // that the alpha value only increases. This should not affect running animations, only // a starting point for a new animation when a different view is bound to this target. record.alpha = minOf(1f, maxOf(record.alpha, t.alpha)) } } }