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 106 private fun getDimen(id: Int): Float { 107 return resources.getDimension(id) 108 } 109 110 private fun getDimenFloat(id: Int): Float { 111 return TypedValue().run { resources.getValue(id, this, true); float } 112 } 113 114 private fun getPx(id: Int): Int { 115 return resources.getDimensionPixelSize(id) 116 } 117 118 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 328 fun createSpring(stiffness: Float, dampingRatio: Float): SpringForce { 329 return SpringForce().setStiffness(stiffness).setDampingRatio(dampingRatio) 330 }