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 17 package com.android.systemui.toast 18 19 import android.animation.ObjectAnimator 20 import android.view.View 21 import android.view.animation.LinearInterpolator 22 import android.view.animation.PathInterpolator 23 import android.animation.AnimatorSet 24 25 class ToastDefaultAnimation { 26 /** 27 * sum of the in and out animation durations cannot exceed 28 * [com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_ANIM_BUFFER] to prevent the toast 29 * window from being removed before animations are completed 30 */ 31 companion object { 32 // total duration shouldn't exceed NotificationManagerService's delay for "in" animation toastInnull33 fun toastIn(view: View): AnimatorSet? { 34 val icon: View? = view.findViewById(com.android.systemui.R.id.icon) 35 val text: View? = view.findViewById(com.android.systemui.R.id.text) 36 if (icon == null || text == null) { 37 return null 38 } 39 val linearInterp = LinearInterpolator() 40 val scaleInterp = PathInterpolator(0f, 0f, 0f, 1f) 41 val sX = ObjectAnimator.ofFloat(view, "scaleX", 0.9f, 1f).apply { 42 interpolator = scaleInterp 43 duration = 333 44 } 45 val sY = ObjectAnimator.ofFloat(view, "scaleY", 0.9f, 1f).apply { 46 interpolator = scaleInterp 47 duration = 333 48 } 49 val vA = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f).apply { 50 interpolator = linearInterp 51 duration = 66 52 } 53 text.alpha = 0f // Set now otherwise won't apply until start delay 54 val tA = ObjectAnimator.ofFloat(text, "alpha", 0f, 1f).apply { 55 interpolator = linearInterp 56 duration = 283 57 startDelay = 50 58 } 59 icon.alpha = 0f // Set now otherwise won't apply until start delay 60 val iA = ObjectAnimator.ofFloat(icon, "alpha", 0f, 1f).apply { 61 interpolator = linearInterp 62 duration = 283 63 startDelay = 50 64 } 65 return AnimatorSet().apply { 66 playTogether(sX, sY, vA, tA, iA) 67 } 68 } 69 toastOutnull70 fun toastOut(view: View): AnimatorSet? { 71 // total duration shouldn't exceed NotificationManagerService's delay for "out" anim 72 val icon: View? = view.findViewById(com.android.systemui.R.id.icon) 73 val text: View? = view.findViewById(com.android.systemui.R.id.text) 74 if (icon == null || text == null) { 75 return null 76 } 77 val linearInterp = LinearInterpolator() 78 val scaleInterp = PathInterpolator(0.3f, 0f, 1f, 1f) 79 val viewScaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f).apply { 80 interpolator = scaleInterp 81 duration = 250 82 } 83 val viewScaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f).apply { 84 interpolator = scaleInterp 85 duration = 250 86 } 87 val viewElevation = ObjectAnimator.ofFloat(view, "elevation", 88 view.elevation, 0f).apply { 89 interpolator = linearInterp 90 duration = 40 91 startDelay = 150 92 } 93 val viewAlpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply { 94 interpolator = linearInterp 95 duration = 100 96 startDelay = 150 97 } 98 val textAlpha = ObjectAnimator.ofFloat(text, "alpha", 1f, 0f).apply { 99 interpolator = linearInterp 100 duration = 166 101 } 102 val iconAlpha = ObjectAnimator.ofFloat(icon, "alpha", 1f, 0f).apply { 103 interpolator = linearInterp 104 duration = 166 105 } 106 return AnimatorSet().apply { 107 playTogether( 108 viewScaleX, 109 viewScaleY, 110 viewElevation, 111 viewAlpha, 112 textAlpha, 113 iconAlpha) 114 } 115 } 116 } 117 } 118