1 package com.android.systemui.navigationbar.gestural
2
3 import android.content.res.Resources
4 import android.util.TypedValue
5 import androidx.core.animation.Interpolator
6 import androidx.core.animation.PathInterpolator
7 import androidx.dynamicanimation.animation.SpringForce
8 import com.android.systemui.R
9
10 data class EdgePanelParams(private var resources: Resources) {
11
12 data class ArrowDimens(
13 val length: Float? = 0f,
14 val height: Float? = 0f,
15 val alpha: Float = 0f,
16 val heightSpring: SpringForce? = null,
17 val lengthSpring: SpringForce? = null,
18 var alphaSpring: Step<SpringForce>? = null,
19 var alphaInterpolator: Step<Float>? = null
20 )
21
22 data class BackgroundDimens(
23 val width: Float? = 0f,
24 val height: Float = 0f,
25 val edgeCornerRadius: Float = 0f,
26 val farCornerRadius: Float = 0f,
27 val alpha: Float = 0f,
28 val widthSpring: SpringForce? = null,
29 val heightSpring: SpringForce? = null,
30 val farCornerRadiusSpring: SpringForce? = null,
31 val edgeCornerRadiusSpring: SpringForce? = null,
32 val alphaSpring: SpringForce? = null,
33 )
34
35 data class BackIndicatorDimens(
36 val horizontalTranslation: Float? = 0f,
37 val scale: Float = 0f,
38 val scalePivotX: Float? = null,
39 val arrowDimens: ArrowDimens,
40 val backgroundDimens: BackgroundDimens,
41 val verticalTranslationSpring: SpringForce? = null,
42 val horizontalTranslationSpring: SpringForce? = null,
43 val scaleSpring: SpringForce? = null,
44 )
45
46 lateinit var entryIndicator: BackIndicatorDimens
47 private set
48 lateinit var activeIndicator: BackIndicatorDimens
49 private set
50 lateinit var cancelledIndicator: BackIndicatorDimens
51 private set
52 lateinit var flungIndicator: BackIndicatorDimens
53 private set
54 lateinit var committedIndicator: BackIndicatorDimens
55 private set
56 lateinit var preThresholdIndicator: BackIndicatorDimens
57 private set
58 lateinit var fullyStretchedIndicator: BackIndicatorDimens
59 private set
60
61 // navigation bar edge constants
62 var arrowPaddingEnd: Int = 0
63 private set
64 var arrowThickness: Float = 0f
65 private set
66 // The closest to y
67 var minArrowYPosition: Int = 0
68 private set
69 var fingerOffset: Int = 0
70 private set
71 var staticTriggerThreshold: Float = 0f
72 private set
73 var reactivationTriggerThreshold: Float = 0f
74 private set
75 var deactivationTriggerThreshold: Float = 0f
76 get() = -field
77 private set
78 lateinit var dynamicTriggerThresholdRange: ClosedRange<Float>
79 private set
80 var swipeProgressThreshold: Float = 0f
81 private set
82
83 lateinit var entryWidthInterpolator: Interpolator
84 private set
85 lateinit var entryWidthTowardsEdgeInterpolator: Interpolator
86 private set
87 lateinit var activeWidthInterpolator: Interpolator
88 private set
89 lateinit var arrowAngleInterpolator: Interpolator
90 private set
91 lateinit var horizontalTranslationInterpolator: Interpolator
92 private set
93 lateinit var verticalTranslationInterpolator: Interpolator
94 private set
95 lateinit var farCornerInterpolator: Interpolator
96 private set
97 lateinit var edgeCornerInterpolator: Interpolator
98 private set
99 lateinit var heightInterpolator: Interpolator
100 private set
101
102 init {
103 update(resources)
104 }
105
getDimennull106 private fun getDimen(id: Int): Float {
107 return resources.getDimension(id)
108 }
109
getDimenFloatnull110 private fun getDimenFloat(id: Int): Float {
111 return TypedValue().run { resources.getValue(id, this, true); float }
112 }
113
getPxnull114 private fun getPx(id: Int): Int {
115 return resources.getDimensionPixelSize(id)
116 }
117
updatenull118 fun update(resources: Resources) {
119 this.resources = resources
120 arrowThickness = getDimen(R.dimen.navigation_edge_arrow_thickness)
121 arrowPaddingEnd = getPx(R.dimen.navigation_edge_panel_padding)
122 minArrowYPosition = getPx(R.dimen.navigation_edge_arrow_min_y)
123 fingerOffset = getPx(R.dimen.navigation_edge_finger_offset)
124 staticTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
125 reactivationTriggerThreshold =
126 getDimen(R.dimen.navigation_edge_action_reactivation_drag_threshold)
127 deactivationTriggerThreshold =
128 getDimen(R.dimen.navigation_edge_action_deactivation_drag_threshold)
129 dynamicTriggerThresholdRange =
130 reactivationTriggerThreshold..deactivationTriggerThreshold
131 swipeProgressThreshold = getDimen(R.dimen.navigation_edge_action_progress_threshold)
132
133 entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
134 entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
135 activeWidthInterpolator = PathInterpolator(.7f, -0.24f, .48f, 1.21f)
136 arrowAngleInterpolator = entryWidthInterpolator
137 horizontalTranslationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
138 verticalTranslationInterpolator = PathInterpolator(.5f, 1.15f, .41f, .94f)
139 farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
140 edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
141 heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
142
143 val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
144 val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
145 val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
146 val flungCommittedFarCornerSpring = createSpring(10000f, 1f)
147 val flungCommittedWidthSpring = createSpring(10000f, 1f)
148 val flungCommittedHeightSpring = createSpring(10000f, 1f)
149
150 val commonArrowDimensAlphaThreshold = .165f
151 val commonArrowDimensAlphaFactor = 1.05f
152 val commonArrowDimensAlphaSpring = Step(
153 threshold = commonArrowDimensAlphaThreshold,
154 factor = commonArrowDimensAlphaFactor,
155 postThreshold = createSpring(180f, 0.9f),
156 preThreshold = createSpring(2000f, 0.6f)
157 )
158 val commonArrowDimensAlphaSpringInterpolator = Step(
159 threshold = commonArrowDimensAlphaThreshold,
160 factor = commonArrowDimensAlphaFactor,
161 postThreshold = 1f,
162 preThreshold = 0f
163 )
164
165 entryIndicator = BackIndicatorDimens(
166 horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
167 scale = getDimenFloat(R.dimen.navigation_edge_entry_scale),
168 scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
169 horizontalTranslationSpring = createSpring(800f, 0.76f),
170 verticalTranslationSpring = createSpring(30000f, 1f),
171 scaleSpring = createSpring(120f, 0.8f),
172 arrowDimens = ArrowDimens(
173 length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
174 height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
175 alpha = 0f,
176 lengthSpring = createSpring(600f, 0.4f),
177 heightSpring = createSpring(600f, 0.4f),
178 alphaSpring = commonArrowDimensAlphaSpring,
179 alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
180 ),
181 backgroundDimens = BackgroundDimens(
182 alpha = 1f,
183 width = getDimen(R.dimen.navigation_edge_entry_background_width),
184 height = getDimen(R.dimen.navigation_edge_entry_background_height),
185 edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
186 farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
187 widthSpring = createSpring(450f, 0.65f),
188 heightSpring = createSpring(1500f, 0.45f),
189 farCornerRadiusSpring = createSpring(300f, 0.5f),
190 edgeCornerRadiusSpring = createSpring(150f, 0.5f),
191 )
192 )
193
194 activeIndicator = BackIndicatorDimens(
195 horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
196 scale = getDimenFloat(R.dimen.navigation_edge_active_scale),
197 horizontalTranslationSpring = createSpring(1000f, 0.8f),
198 scaleSpring = createSpring(325f, 0.55f),
199 scalePivotX = getDimen(R.dimen.navigation_edge_active_background_width),
200 arrowDimens = ArrowDimens(
201 length = getDimen(R.dimen.navigation_edge_active_arrow_length),
202 height = getDimen(R.dimen.navigation_edge_active_arrow_height),
203 alpha = 1f,
204 lengthSpring = activeCommittedArrowLengthSpring,
205 heightSpring = activeCommittedArrowHeightSpring,
206 alphaSpring = commonArrowDimensAlphaSpring,
207 alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
208 ),
209 backgroundDimens = BackgroundDimens(
210 alpha = 1f,
211 width = getDimen(R.dimen.navigation_edge_active_background_width),
212 height = getDimen(R.dimen.navigation_edge_active_background_height),
213 edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
214 farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners),
215 widthSpring = createSpring(850f, 0.75f),
216 heightSpring = createSpring(10000f, 1f),
217 edgeCornerRadiusSpring = createSpring(2600f, 0.855f),
218 farCornerRadiusSpring = createSpring(1200f, 0.30f),
219 )
220 )
221
222 preThresholdIndicator = BackIndicatorDimens(
223 horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
224 scale = getDimenFloat(R.dimen.navigation_edge_pre_threshold_scale),
225 scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
226 scaleSpring = createSpring(120f, 0.8f),
227 horizontalTranslationSpring = createSpring(6000f, 1f),
228 arrowDimens = ArrowDimens(
229 length = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_length),
230 height = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_height),
231 alpha = 1f,
232 lengthSpring = createSpring(100f, 0.6f),
233 heightSpring = createSpring(100f, 0.6f),
234 alphaSpring = commonArrowDimensAlphaSpring,
235 alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
236 ),
237 backgroundDimens = BackgroundDimens(
238 alpha = 1f,
239 width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
240 height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
241 edgeCornerRadius =
242 getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
243 farCornerRadius =
244 getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
245 widthSpring = createSpring(650f, 1f),
246 heightSpring = createSpring(1500f, 0.45f),
247 farCornerRadiusSpring = createSpring(300f, 1f),
248 edgeCornerRadiusSpring = createSpring(250f, 0.5f),
249 )
250 )
251
252 committedIndicator = activeIndicator.copy(
253 horizontalTranslation = null,
254 scalePivotX = null,
255 arrowDimens = activeIndicator.arrowDimens.copy(
256 lengthSpring = activeCommittedArrowLengthSpring,
257 heightSpring = activeCommittedArrowHeightSpring,
258 length = null,
259 height = null,
260 ),
261 backgroundDimens = activeIndicator.backgroundDimens.copy(
262 alpha = 0f,
263 // explicitly set to null to preserve previous width upon state change
264 width = null,
265 widthSpring = flungCommittedWidthSpring,
266 heightSpring = flungCommittedHeightSpring,
267 edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
268 farCornerRadiusSpring = flungCommittedFarCornerSpring,
269 alphaSpring = createSpring(1400f, 1f),
270 ),
271 scale = 0.86f,
272 scaleSpring = createSpring(5700f, 1f),
273 )
274
275 flungIndicator = committedIndicator.copy(
276 arrowDimens = committedIndicator.arrowDimens.copy(
277 lengthSpring = createSpring(850f, 0.46f),
278 heightSpring = createSpring(850f, 0.46f),
279 length = activeIndicator.arrowDimens.length,
280 height = activeIndicator.arrowDimens.height
281 ),
282 backgroundDimens = committedIndicator.backgroundDimens.copy(
283 widthSpring = flungCommittedWidthSpring,
284 heightSpring = flungCommittedHeightSpring,
285 edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
286 farCornerRadiusSpring = flungCommittedFarCornerSpring,
287 )
288 )
289
290 cancelledIndicator = entryIndicator.copy(
291 backgroundDimens = entryIndicator.backgroundDimens.copy(
292 width = 0f,
293 alpha = 0f,
294 alphaSpring = createSpring(450f, 1f)
295 )
296 )
297
298 fullyStretchedIndicator = BackIndicatorDimens(
299 horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
300 scale = getDimenFloat(R.dimen.navigation_edge_stretch_scale),
301 horizontalTranslationSpring = null,
302 verticalTranslationSpring = null,
303 scaleSpring = null,
304 arrowDimens = ArrowDimens(
305 length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
306 height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
307 alpha = 1f,
308 alphaSpring = null,
309 heightSpring = null,
310 lengthSpring = null,
311 ),
312 backgroundDimens = BackgroundDimens(
313 alpha = 1f,
314 width = getDimen(R.dimen.navigation_edge_stretch_background_width),
315 height = getDimen(R.dimen.navigation_edge_stretch_background_height),
316 edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
317 farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners),
318 alphaSpring = null,
319 widthSpring = null,
320 heightSpring = null,
321 edgeCornerRadiusSpring = null,
322 farCornerRadiusSpring = null,
323 )
324 )
325 }
326 }
327
createSpringnull328 fun createSpring(stiffness: Float, dampingRatio: Float): SpringForce {
329 return SpringForce().setStiffness(stiffness).setDampingRatio(dampingRatio)
330 }