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.res.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 
49     lateinit var activeIndicator: BackIndicatorDimens
50         private set
51 
52     lateinit var cancelledIndicator: BackIndicatorDimens
53         private set
54 
55     lateinit var flungIndicator: BackIndicatorDimens
56         private set
57 
58     lateinit var committedIndicator: BackIndicatorDimens
59         private set
60 
61     lateinit var preThresholdIndicator: BackIndicatorDimens
62         private set
63 
64     lateinit var fullyStretchedIndicator: BackIndicatorDimens
65         private set
66 
67     // navigation bar edge constants
68     var arrowPaddingEnd: Int = 0
69         private set
70 
71     var arrowThickness: Float = 0f
72         private set
73 
74     // The closest to y
75     var minArrowYPosition: Int = 0
76         private set
77 
78     var fingerOffset: Int = 0
79         private set
80 
81     var staticTriggerThreshold: Float = 0f
82         private set
83 
84     var reactivationTriggerThreshold: Float = 0f
85         private set
86 
87     var deactivationTriggerThreshold: Float = 0f
88         get() = -field
89         private set
90 
91     lateinit var dynamicTriggerThresholdRange: ClosedRange<Float>
92         private set
93 
94     var swipeProgressThreshold: Float = 0f
95         private set
96 
97     lateinit var entryWidthInterpolator: Interpolator
98         private set
99 
100     lateinit var entryWidthTowardsEdgeInterpolator: Interpolator
101         private set
102 
103     lateinit var activeWidthInterpolator: Interpolator
104         private set
105 
106     lateinit var arrowAngleInterpolator: Interpolator
107         private set
108 
109     lateinit var horizontalTranslationInterpolator: Interpolator
110         private set
111 
112     lateinit var verticalTranslationInterpolator: Interpolator
113         private set
114 
115     lateinit var farCornerInterpolator: Interpolator
116         private set
117 
118     lateinit var edgeCornerInterpolator: Interpolator
119         private set
120 
121     lateinit var heightInterpolator: Interpolator
122         private set
123 
124     init {
125         update(resources)
126     }
127 
getDimennull128     private fun getDimen(id: Int): Float {
129         return resources.getDimension(id)
130     }
131 
getDimenFloatnull132     private fun getDimenFloat(id: Int): Float {
133         return TypedValue().run {
134             resources.getValue(id, this, true)
135             float
136         }
137     }
138 
getPxnull139     private fun getPx(id: Int): Int {
140         return resources.getDimensionPixelSize(id)
141     }
142 
updatenull143     fun update(resources: Resources) {
144         this.resources = resources
145         arrowThickness = getDimen(R.dimen.navigation_edge_arrow_thickness)
146         arrowPaddingEnd = getPx(R.dimen.navigation_edge_panel_padding)
147         minArrowYPosition = getPx(R.dimen.navigation_edge_arrow_min_y)
148         fingerOffset = getPx(R.dimen.navigation_edge_finger_offset)
149         staticTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
150         reactivationTriggerThreshold =
151             getDimen(R.dimen.navigation_edge_action_reactivation_drag_threshold)
152         deactivationTriggerThreshold =
153             getDimen(R.dimen.navigation_edge_action_deactivation_drag_threshold)
154         dynamicTriggerThresholdRange = reactivationTriggerThreshold..deactivationTriggerThreshold
155         swipeProgressThreshold = getDimen(R.dimen.navigation_edge_action_progress_threshold)
156 
157         entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
158         entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
159         activeWidthInterpolator = PathInterpolator(.7f, -0.24f, .48f, 1.21f)
160         arrowAngleInterpolator = entryWidthInterpolator
161         horizontalTranslationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
162         verticalTranslationInterpolator = PathInterpolator(.5f, 1.15f, .41f, .94f)
163         farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
164         edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
165         heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
166 
167         val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
168         val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
169         val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
170         val flungCommittedFarCornerSpring = createSpring(10000f, 1f)
171         val flungCommittedWidthSpring = createSpring(10000f, 1f)
172         val flungCommittedHeightSpring = createSpring(10000f, 1f)
173 
174         val commonArrowDimensAlphaThreshold = .165f
175         val commonArrowDimensAlphaFactor = 1.05f
176         val commonArrowDimensAlphaSpring =
177             Step(
178                 threshold = commonArrowDimensAlphaThreshold,
179                 factor = commonArrowDimensAlphaFactor,
180                 postThreshold = createSpring(180f, 0.9f),
181                 preThreshold = createSpring(2000f, 0.6f)
182             )
183         val commonArrowDimensAlphaSpringInterpolator =
184             Step(
185                 threshold = commonArrowDimensAlphaThreshold,
186                 factor = commonArrowDimensAlphaFactor,
187                 postThreshold = 1f,
188                 preThreshold = 0f
189             )
190 
191         entryIndicator =
192             BackIndicatorDimens(
193                 horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
194                 scale = getDimenFloat(R.dimen.navigation_edge_entry_scale),
195                 scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
196                 horizontalTranslationSpring = createSpring(800f, 0.76f),
197                 verticalTranslationSpring = createSpring(30000f, 1f),
198                 scaleSpring = createSpring(120f, 0.8f),
199                 arrowDimens =
200                     ArrowDimens(
201                         length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
202                         height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
203                         alpha = 0f,
204                         lengthSpring = createSpring(600f, 0.4f),
205                         heightSpring = createSpring(600f, 0.4f),
206                         alphaSpring = commonArrowDimensAlphaSpring,
207                         alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
208                     ),
209                 backgroundDimens =
210                     BackgroundDimens(
211                         alpha = 1f,
212                         width = getDimen(R.dimen.navigation_edge_entry_background_width),
213                         height = getDimen(R.dimen.navigation_edge_entry_background_height),
214                         edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
215                         farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
216                         widthSpring = createSpring(450f, 0.65f),
217                         heightSpring = createSpring(1500f, 0.45f),
218                         farCornerRadiusSpring = createSpring(300f, 0.5f),
219                         edgeCornerRadiusSpring = createSpring(150f, 0.5f),
220                     )
221             )
222 
223         activeIndicator =
224             BackIndicatorDimens(
225                 horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
226                 scale = getDimenFloat(R.dimen.navigation_edge_active_scale),
227                 horizontalTranslationSpring = createSpring(1000f, 0.8f),
228                 scaleSpring = createSpring(325f, 0.55f),
229                 scalePivotX = getDimen(R.dimen.navigation_edge_active_background_width),
230                 arrowDimens =
231                     ArrowDimens(
232                         length = getDimen(R.dimen.navigation_edge_active_arrow_length),
233                         height = getDimen(R.dimen.navigation_edge_active_arrow_height),
234                         alpha = 1f,
235                         lengthSpring = activeCommittedArrowLengthSpring,
236                         heightSpring = activeCommittedArrowHeightSpring,
237                         alphaSpring = commonArrowDimensAlphaSpring,
238                         alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
239                     ),
240                 backgroundDimens =
241                     BackgroundDimens(
242                         alpha = 1f,
243                         width = getDimen(R.dimen.navigation_edge_active_background_width),
244                         height = getDimen(R.dimen.navigation_edge_active_background_height),
245                         edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
246                         farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners),
247                         widthSpring = createSpring(850f, 0.75f),
248                         heightSpring = createSpring(10000f, 1f),
249                         edgeCornerRadiusSpring = createSpring(2600f, 0.855f),
250                         farCornerRadiusSpring = createSpring(1200f, 0.30f),
251                     )
252             )
253 
254         preThresholdIndicator =
255             BackIndicatorDimens(
256                 horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
257                 scale = getDimenFloat(R.dimen.navigation_edge_pre_threshold_scale),
258                 scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
259                 scaleSpring = createSpring(120f, 0.8f),
260                 horizontalTranslationSpring = createSpring(6000f, 1f),
261                 arrowDimens =
262                     ArrowDimens(
263                         length = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_length),
264                         height = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_height),
265                         alpha = 1f,
266                         lengthSpring = createSpring(100f, 0.6f),
267                         heightSpring = createSpring(100f, 0.6f),
268                         alphaSpring = commonArrowDimensAlphaSpring,
269                         alphaInterpolator = commonArrowDimensAlphaSpringInterpolator
270                     ),
271                 backgroundDimens =
272                     BackgroundDimens(
273                         alpha = 1f,
274                         width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
275                         height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
276                         edgeCornerRadius =
277                             getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
278                         farCornerRadius =
279                             getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
280                         widthSpring = createSpring(650f, 1f),
281                         heightSpring = createSpring(1500f, 0.45f),
282                         farCornerRadiusSpring = createSpring(300f, 1f),
283                         edgeCornerRadiusSpring = createSpring(250f, 0.5f),
284                     )
285             )
286 
287         committedIndicator =
288             activeIndicator.copy(
289                 horizontalTranslation = null,
290                 scalePivotX = null,
291                 arrowDimens =
292                     activeIndicator.arrowDimens.copy(
293                         lengthSpring = activeCommittedArrowLengthSpring,
294                         heightSpring = activeCommittedArrowHeightSpring,
295                         length = null,
296                         height = null,
297                     ),
298                 backgroundDimens =
299                     activeIndicator.backgroundDimens.copy(
300                         alpha = 0f,
301                         // explicitly set to null to preserve previous width upon state change
302                         width = null,
303                         widthSpring = flungCommittedWidthSpring,
304                         heightSpring = flungCommittedHeightSpring,
305                         edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
306                         farCornerRadiusSpring = flungCommittedFarCornerSpring,
307                         alphaSpring = createSpring(1400f, 1f),
308                     ),
309                 scale = 0.86f,
310                 scaleSpring = createSpring(5700f, 1f),
311             )
312 
313         flungIndicator =
314             committedIndicator.copy(
315                 arrowDimens =
316                     committedIndicator.arrowDimens.copy(
317                         lengthSpring = createSpring(850f, 0.46f),
318                         heightSpring = createSpring(850f, 0.46f),
319                         length = activeIndicator.arrowDimens.length,
320                         height = activeIndicator.arrowDimens.height
321                     ),
322                 backgroundDimens =
323                     committedIndicator.backgroundDimens.copy(
324                         widthSpring = flungCommittedWidthSpring,
325                         heightSpring = flungCommittedHeightSpring,
326                         edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
327                         farCornerRadiusSpring = flungCommittedFarCornerSpring,
328                     )
329             )
330 
331         cancelledIndicator =
332             entryIndicator.copy(
333                 backgroundDimens =
334                     entryIndicator.backgroundDimens.copy(
335                         width = 0f,
336                         alpha = 0f,
337                         alphaSpring = createSpring(450f, 1f)
338                     )
339             )
340 
341         fullyStretchedIndicator =
342             BackIndicatorDimens(
343                 horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
344                 scale = getDimenFloat(R.dimen.navigation_edge_stretch_scale),
345                 horizontalTranslationSpring = null,
346                 verticalTranslationSpring = null,
347                 scaleSpring = null,
348                 arrowDimens =
349                     ArrowDimens(
350                         length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
351                         height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
352                         alpha = 1f,
353                         alphaSpring = null,
354                         heightSpring = null,
355                         lengthSpring = null,
356                     ),
357                 backgroundDimens =
358                     BackgroundDimens(
359                         alpha = 1f,
360                         width = getDimen(R.dimen.navigation_edge_stretch_background_width),
361                         height = getDimen(R.dimen.navigation_edge_stretch_background_height),
362                         edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
363                         farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners),
364                         alphaSpring = null,
365                         widthSpring = null,
366                         heightSpring = null,
367                         edgeCornerRadiusSpring = null,
368                         farCornerRadiusSpring = null,
369                     )
370             )
371     }
372 }
373 
createSpringnull374 fun createSpring(stiffness: Float, dampingRatio: Float): SpringForce {
375     return SpringForce().setStiffness(stiffness).setDampingRatio(dampingRatio)
376 }
377