1 /*
<lambda>null2  * Copyright (C) 2022 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.keyguard
18 
19 import android.animation.Animator
20 import android.animation.AnimatorListenerAdapter
21 import android.animation.AnimatorSet
22 import android.animation.ObjectAnimator
23 import android.content.Context
24 import android.content.res.ColorStateList
25 import android.util.AttributeSet
26 import android.view.View
27 import com.android.app.animation.Interpolators
28 import com.android.settingslib.Utils
29 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.TITLE
30 
31 /** Displays security messages for the keyguard bouncer. */
32 open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) :
33     KeyguardMessageArea(context, attrs) {
34     private val DEFAULT_COLOR = -1
35     private var mDefaultColorState: ColorStateList? = null
36     private var mNextMessageColorState: ColorStateList? = ColorStateList.valueOf(DEFAULT_COLOR)
37     private val animatorSet = AnimatorSet()
38     private var textAboutToShow: CharSequence? = null
39     protected open val SHOW_DURATION_MILLIS = 150L
40     protected open val HIDE_DURATION_MILLIS = 200L
41 
42     override fun onFinishInflate() {
43         super.onFinishInflate()
44         mDefaultColorState = getColorInStyle()
45     }
46 
47     private fun getColorInStyle(): ColorStateList? {
48         val styledAttributes =
49             context.obtainStyledAttributes(styleResId, intArrayOf(android.R.attr.textColor))
50         var colorStateList: ColorStateList? = null
51         if (styledAttributes != null) {
52             colorStateList = styledAttributes.getColorStateList(0)
53         }
54         styledAttributes.recycle()
55         return colorStateList
56     }
57 
58     override fun updateTextColor() {
59         var colorState = mDefaultColorState
60         mNextMessageColorState?.defaultColor?.let { color ->
61             if (color != DEFAULT_COLOR) {
62                 colorState = mNextMessageColorState
63                 mNextMessageColorState = mDefaultColorState ?: ColorStateList.valueOf(DEFAULT_COLOR)
64             }
65         }
66         setTextColor(colorState)
67     }
68 
69     override fun setNextMessageColor(colorState: ColorStateList?) {
70         mNextMessageColorState = colorState
71     }
72 
73     override fun onThemeChanged() {
74         mDefaultColorState = getColorInStyle() ?: Utils.getColorAttr(context, TITLE)
75         super.onThemeChanged()
76     }
77 
78     override fun reloadColor() {
79         mDefaultColorState = getColorInStyle() ?: Utils.getColorAttr(context, TITLE)
80         super.reloadColor()
81     }
82 
83     override fun setMessage(msg: CharSequence?, animate: Boolean) {
84         if ((msg == textAboutToShow && msg != null) || msg == text) {
85             return
86         }
87 
88         if (!animate) {
89             super.setMessage(msg, animate)
90             return
91         }
92 
93         textAboutToShow = msg
94 
95         if (animatorSet.isRunning) {
96             animatorSet.cancel()
97             textAboutToShow = null
98         }
99 
100         val hideAnimator =
101             ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f).apply {
102                 duration = HIDE_DURATION_MILLIS
103                 interpolator = Interpolators.STANDARD_ACCELERATE
104             }
105 
106         hideAnimator.addListener(
107             object : AnimatorListenerAdapter() {
108                 override fun onAnimationEnd(animation: Animator) {
109                     super@BouncerKeyguardMessageArea.setMessage(msg, animate)
110                 }
111             }
112         )
113         val showAnimator =
114             ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f).apply {
115                 duration = SHOW_DURATION_MILLIS
116                 interpolator = Interpolators.STANDARD_DECELERATE
117             }
118 
119         showAnimator.addListener(
120             object : AnimatorListenerAdapter() {
121                 override fun onAnimationEnd(animation: Animator) {
122                     textAboutToShow = null
123                 }
124             }
125         )
126 
127         animatorSet.playSequentially(hideAnimator, showAnimator)
128         animatorSet.start()
129     }
130 }
131