Merge "DO NOT MERGE New Back Arrow in production" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
225ce14f0e
@@ -43,12 +43,18 @@
|
||||
<dimen name="navigation_edge_panel_height">268dp</dimen>
|
||||
<!-- The threshold to drag to trigger the edge action -->
|
||||
<dimen name="navigation_edge_action_drag_threshold">16dp</dimen>
|
||||
<!-- The drag distance to consider evaluating gesture -->
|
||||
<dimen name="navigation_edge_action_min_distance_to_start_animation">24dp</dimen>
|
||||
<!-- The threshold to progress back animation for edge swipe -->
|
||||
<dimen name="navigation_edge_action_progress_threshold">412dp</dimen>
|
||||
<!-- The minimum display position of the arrow on the screen -->
|
||||
<dimen name="navigation_edge_arrow_min_y">64dp</dimen>
|
||||
<!-- The amount by which the arrow is shifted to avoid the finger-->
|
||||
<dimen name="navigation_edge_finger_offset">64dp</dimen>
|
||||
<!-- The threshold to dynamically activate the edge action -->
|
||||
<dimen name="navigation_edge_action_reactivation_drag_threshold">32dp</dimen>
|
||||
<!-- The threshold to dynamically deactivate the edge action -->
|
||||
<dimen name="navigation_edge_action_deactivation_drag_threshold">32dp</dimen>
|
||||
|
||||
<!-- The thickness of the arrow -->
|
||||
<dimen name="navigation_edge_arrow_thickness">4dp</dimen>
|
||||
@@ -56,37 +62,61 @@
|
||||
<dimen name="navigation_edge_minimum_x_delta_for_switch">32dp</dimen>
|
||||
|
||||
<!-- entry state -->
|
||||
<item name="navigation_edge_entry_scale" format="float" type="dimen">0.98</item>
|
||||
<dimen name="navigation_edge_entry_margin">4dp</dimen>
|
||||
<dimen name="navigation_edge_entry_background_width">8dp</dimen>
|
||||
<dimen name="navigation_edge_entry_background_height">60dp</dimen>
|
||||
<dimen name="navigation_edge_entry_edge_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_entry_far_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_entry_arrow_length">10dp</dimen>
|
||||
<dimen name="navigation_edge_entry_arrow_height">7dp</dimen>
|
||||
<item name="navigation_edge_entry_background_alpha" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_entry_background_width">0dp</dimen>
|
||||
<dimen name="navigation_edge_entry_background_height">48dp</dimen>
|
||||
<dimen name="navigation_edge_entry_edge_corners">6dp</dimen>
|
||||
<dimen name="navigation_edge_entry_far_corners">6dp</dimen>
|
||||
<item name="navigation_edge_entry_arrow_alpha" format="float" type="dimen">0.0</item>
|
||||
<dimen name="navigation_edge_entry_arrow_length">8.6dp</dimen>
|
||||
<dimen name="navigation_edge_entry_arrow_height">5dp</dimen>
|
||||
|
||||
<!-- pre-threshold -->
|
||||
<dimen name="navigation_edge_pre_threshold_margin">4dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_background_width">64dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_background_height">60dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_edge_corners">22dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_far_corners">26dp</dimen>
|
||||
<item name="navigation_edge_pre_threshold_background_alpha" format="float" type="dimen">1.0
|
||||
</item>
|
||||
<item name="navigation_edge_pre_threshold_scale" format="float" type="dimen">0.98</item>
|
||||
<dimen name="navigation_edge_pre_threshold_background_width">51dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_background_height">46dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_edge_corners">16dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_far_corners">20dp</dimen>
|
||||
<item name="navigation_edge_pre_threshold_arrow_alpha" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_pre_threshold_arrow_length">8dp</dimen>
|
||||
<dimen name="navigation_edge_pre_threshold_arrow_height">5.6dp</dimen>
|
||||
|
||||
<!-- post-threshold / active -->
|
||||
<!-- active (post-threshold) -->
|
||||
<item name="navigation_edge_active_scale" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_active_margin">14dp</dimen>
|
||||
<dimen name="navigation_edge_active_background_width">60dp</dimen>
|
||||
<dimen name="navigation_edge_active_background_height">60dp</dimen>
|
||||
<dimen name="navigation_edge_active_edge_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_active_far_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_active_arrow_length">8dp</dimen>
|
||||
<dimen name="navigation_edge_active_arrow_height">9dp</dimen>
|
||||
<item name="navigation_edge_active_background_alpha" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_active_background_width">48dp</dimen>
|
||||
<dimen name="navigation_edge_active_background_height">48dp</dimen>
|
||||
<dimen name="navigation_edge_active_edge_corners">24dp</dimen>
|
||||
<dimen name="navigation_edge_active_far_corners">24dp</dimen>
|
||||
<item name="navigation_edge_active_arrow_alpha" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_active_arrow_length">6.4dp</dimen>
|
||||
<dimen name="navigation_edge_active_arrow_height">7.2dp</dimen>
|
||||
|
||||
<!-- committed -->
|
||||
<item name="navigation_edge_committed_scale" format="float" type="dimen">0.85</item>
|
||||
<item name="navigation_edge_committed_alpha" format="float" type="dimen">0</item>
|
||||
|
||||
<!-- cancelled -->
|
||||
<dimen name="navigation_edge_cancelled_background_width">0dp</dimen>
|
||||
|
||||
<item name="navigation_edge_stretch_scale" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_stretch_margin">18dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_background_width">74dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_background_height">60dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_edge_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_far_corners">30dp</dimen>
|
||||
<dimen name="navigation_edge_stretched_arrow_length">7dp</dimen>
|
||||
<dimen name="navigation_edge_stretched_arrow_height">10dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_background_width">60dp</dimen>
|
||||
<item name="navigation_edge_stretch_background_alpha" format="float" type="dimen">
|
||||
@dimen/navigation_edge_entry_background_alpha
|
||||
</item>
|
||||
<dimen name="navigation_edge_stretch_background_height">48dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_edge_corners">24dp</dimen>
|
||||
<dimen name="navigation_edge_stretch_far_corners">24dp</dimen>
|
||||
<item name="navigation_edge_strech_arrow_alpha" format="float" type="dimen">1.0</item>
|
||||
<dimen name="navigation_edge_stretched_arrow_length">5.6dp</dimen>
|
||||
<dimen name="navigation_edge_stretched_arrow_height">8dp</dimen>
|
||||
|
||||
<dimen name="navigation_edge_cancelled_arrow_length">12dp</dimen>
|
||||
<dimen name="navigation_edge_cancelled_arrow_height">0dp</dimen>
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package com.android.systemui.navigationbar.gestural
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import android.graphics.RectF
|
||||
import android.util.MathUtils.min
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.dynamicanimation.animation.FloatPropertyCompat
|
||||
import androidx.dynamicanimation.animation.SpringAnimation
|
||||
import androidx.dynamicanimation.animation.SpringForce
|
||||
import com.android.internal.R.style.Theme_DeviceDefault
|
||||
import com.android.internal.util.LatencyTracker
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.systemui.navigationbar.gestural.BackPanelController.DelayedOnAnimationEndListener
|
||||
@@ -16,7 +22,10 @@ import com.android.systemui.navigationbar.gestural.BackPanelController.DelayedOn
|
||||
private const val TAG = "BackPanel"
|
||||
private const val DEBUG = false
|
||||
|
||||
class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : View(context) {
|
||||
class BackPanel(
|
||||
context: Context,
|
||||
private val latencyTracker: LatencyTracker
|
||||
) : View(context) {
|
||||
|
||||
var arrowsPointLeft = false
|
||||
set(value) {
|
||||
@@ -45,52 +54,54 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
/**
|
||||
* The length of the arrow measured horizontally. Used for animating [arrowPath]
|
||||
*/
|
||||
private var arrowLength = AnimatedFloat("arrowLength", SpringForce())
|
||||
private var arrowLength = AnimatedFloat(
|
||||
name = "arrowLength",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS
|
||||
)
|
||||
|
||||
/**
|
||||
* The height of the arrow measured vertically from its center to its top (i.e. half the total
|
||||
* height). Used for animating [arrowPath]
|
||||
*/
|
||||
private var arrowHeight = AnimatedFloat("arrowHeight", SpringForce())
|
||||
|
||||
private val backgroundWidth = AnimatedFloat(
|
||||
name = "backgroundWidth",
|
||||
SpringForce().apply {
|
||||
stiffness = 600f
|
||||
dampingRatio = 0.65f
|
||||
}
|
||||
var arrowHeight = AnimatedFloat(
|
||||
name = "arrowHeight",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ROTATION_DEGREES
|
||||
)
|
||||
|
||||
private val backgroundHeight = AnimatedFloat(
|
||||
name = "backgroundHeight",
|
||||
SpringForce().apply {
|
||||
stiffness = 600f
|
||||
dampingRatio = 0.65f
|
||||
}
|
||||
val backgroundWidth = AnimatedFloat(
|
||||
name = "backgroundWidth",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
|
||||
minimumValue = 0f,
|
||||
)
|
||||
|
||||
val backgroundHeight = AnimatedFloat(
|
||||
name = "backgroundHeight",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
|
||||
minimumValue = 0f,
|
||||
)
|
||||
|
||||
/**
|
||||
* Corners of the background closer to the edge of the screen (where the arrow appeared from).
|
||||
* Used for animating [arrowBackgroundRect]
|
||||
*/
|
||||
private val backgroundEdgeCornerRadius = AnimatedFloat(
|
||||
name = "backgroundEdgeCornerRadius",
|
||||
SpringForce().apply {
|
||||
stiffness = 400f
|
||||
dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
|
||||
}
|
||||
)
|
||||
val backgroundEdgeCornerRadius = AnimatedFloat("backgroundEdgeCornerRadius")
|
||||
|
||||
/**
|
||||
* Corners of the background further from the edge of the screens (toward the direction the
|
||||
* arrow is being dragged). Used for animating [arrowBackgroundRect]
|
||||
*/
|
||||
private val backgroundFarCornerRadius = AnimatedFloat(
|
||||
name = "backgroundDragCornerRadius",
|
||||
SpringForce().apply {
|
||||
stiffness = 2200f
|
||||
dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
|
||||
}
|
||||
val backgroundFarCornerRadius = AnimatedFloat("backgroundFarCornerRadius")
|
||||
|
||||
var scale = AnimatedFloat(
|
||||
name = "scale",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_SCALE,
|
||||
minimumValue = 0f
|
||||
)
|
||||
|
||||
val scalePivotX = AnimatedFloat(
|
||||
name = "scalePivotX",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
|
||||
minimumValue = backgroundWidth.pos / 2,
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -98,34 +109,40 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
* background's margin relative to the screen edge. The arrow will be centered within the
|
||||
* background.
|
||||
*/
|
||||
private var horizontalTranslation = AnimatedFloat("horizontalTranslation", SpringForce())
|
||||
var horizontalTranslation = AnimatedFloat(name = "horizontalTranslation")
|
||||
|
||||
private val currentAlpha: FloatPropertyCompat<BackPanel> =
|
||||
object : FloatPropertyCompat<BackPanel>("currentAlpha") {
|
||||
override fun setValue(panel: BackPanel, value: Float) {
|
||||
panel.alpha = value
|
||||
}
|
||||
var arrowAlpha = AnimatedFloat(
|
||||
name = "arrowAlpha",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ALPHA,
|
||||
minimumValue = 0f,
|
||||
maximumValue = 1f
|
||||
)
|
||||
|
||||
override fun getValue(panel: BackPanel): Float = panel.alpha
|
||||
}
|
||||
val backgroundAlpha = AnimatedFloat(
|
||||
name = "backgroundAlpha",
|
||||
minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ALPHA,
|
||||
minimumValue = 0f,
|
||||
maximumValue = 1f
|
||||
)
|
||||
|
||||
private val alphaAnimation = SpringAnimation(this, currentAlpha)
|
||||
.setSpring(
|
||||
SpringForce()
|
||||
.setStiffness(60f)
|
||||
.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
|
||||
)
|
||||
private val allAnimatedFloat = setOf(
|
||||
arrowLength,
|
||||
arrowHeight,
|
||||
backgroundWidth,
|
||||
backgroundEdgeCornerRadius,
|
||||
backgroundFarCornerRadius,
|
||||
scalePivotX,
|
||||
scale,
|
||||
horizontalTranslation,
|
||||
arrowAlpha,
|
||||
backgroundAlpha
|
||||
)
|
||||
|
||||
/**
|
||||
* Canvas vertical translation. How far up/down the arrow and background appear relative to the
|
||||
* canvas.
|
||||
*/
|
||||
private var verticalTranslation: AnimatedFloat = AnimatedFloat(
|
||||
name = "verticalTranslation",
|
||||
SpringForce().apply {
|
||||
stiffness = SpringForce.STIFFNESS_MEDIUM
|
||||
}
|
||||
)
|
||||
var verticalTranslation = AnimatedFloat("verticalTranslation")
|
||||
|
||||
/**
|
||||
* Use for drawing debug info. Can only be set if [DEBUG]=true
|
||||
@@ -136,28 +153,67 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
}
|
||||
|
||||
internal fun updateArrowPaint(arrowThickness: Float) {
|
||||
// Arrow constants
|
||||
|
||||
arrowPaint.strokeWidth = arrowThickness
|
||||
|
||||
arrowPaint.color =
|
||||
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
|
||||
arrowBackgroundPaint.color = Utils.getColorAccentDefaultColor(context)
|
||||
val isDeviceInNightTheme = resources.configuration.uiMode and
|
||||
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
val colorControlActivated = ContextThemeWrapper(context, Theme_DeviceDefault)
|
||||
.run {
|
||||
val typedValue = TypedValue()
|
||||
val a: TypedArray = obtainStyledAttributes(typedValue.data,
|
||||
intArrayOf(android.R.attr.colorControlActivated))
|
||||
val color = a.getColor(0, 0)
|
||||
a.recycle()
|
||||
color
|
||||
}
|
||||
|
||||
val colorPrimary =
|
||||
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
|
||||
|
||||
arrowPaint.color = Utils.getColorAccentDefaultColor(context)
|
||||
|
||||
arrowBackgroundPaint.color = if (isDeviceInNightTheme) {
|
||||
colorPrimary
|
||||
} else {
|
||||
colorControlActivated
|
||||
}
|
||||
}
|
||||
|
||||
private inner class AnimatedFloat(name: String, springForce: SpringForce) {
|
||||
inner class AnimatedFloat(
|
||||
name: String,
|
||||
private val minimumVisibleChange: Float? = null,
|
||||
private val minimumValue: Float? = null,
|
||||
private val maximumValue: Float? = null,
|
||||
) {
|
||||
|
||||
// The resting position when not stretched by a touch drag
|
||||
private var restingPosition = 0f
|
||||
|
||||
// The current position as updated by the SpringAnimation
|
||||
var pos = 0f
|
||||
set(v) {
|
||||
private set(v) {
|
||||
if (field != v) {
|
||||
field = v
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
val animation: SpringAnimation
|
||||
private val animation: SpringAnimation
|
||||
var spring: SpringForce
|
||||
get() = animation.spring
|
||||
set(value) {
|
||||
animation.cancel()
|
||||
animation.spring = value
|
||||
}
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = animation.isRunning
|
||||
|
||||
fun addEndListener(listener: DelayedOnAnimationEndListener) {
|
||||
animation.addEndListener(listener)
|
||||
}
|
||||
|
||||
init {
|
||||
val floatProp = object : FloatPropertyCompat<AnimatedFloat>(name) {
|
||||
@@ -167,8 +223,12 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
|
||||
override fun getValue(animatedFloat: AnimatedFloat): Float = animatedFloat.pos
|
||||
}
|
||||
animation = SpringAnimation(this, floatProp)
|
||||
animation.spring = springForce
|
||||
animation = SpringAnimation(this, floatProp).apply {
|
||||
spring = SpringForce()
|
||||
this@AnimatedFloat.minimumValue?.let { setMinValue(it) }
|
||||
this@AnimatedFloat.maximumValue?.let { setMaxValue(it) }
|
||||
this@AnimatedFloat.minimumVisibleChange?.let { minimumVisibleChange = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun snapTo(newPosition: Float) {
|
||||
@@ -178,8 +238,24 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
pos = newPosition
|
||||
}
|
||||
|
||||
fun stretchTo(stretchAmount: Float) {
|
||||
animation.animateToFinalPosition(restingPosition + stretchAmount)
|
||||
fun snapToRestingPosition() {
|
||||
snapTo(restingPosition)
|
||||
}
|
||||
|
||||
|
||||
fun stretchTo(
|
||||
stretchAmount: Float,
|
||||
startingVelocity: Float? = null,
|
||||
springForce: SpringForce? = null
|
||||
) {
|
||||
animation.apply {
|
||||
startingVelocity?.let {
|
||||
cancel()
|
||||
setStartVelocity(it)
|
||||
}
|
||||
springForce?.let { spring = springForce }
|
||||
animateToFinalPosition(restingPosition + stretchAmount)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,18 +264,23 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
*
|
||||
* The [restingPosition] will remain unchanged. Only the animation is updated.
|
||||
*/
|
||||
fun stretchBy(finalPosition: Float, amount: Float) {
|
||||
val stretchedAmount = amount * (finalPosition - restingPosition)
|
||||
fun stretchBy(finalPosition: Float?, amount: Float) {
|
||||
val stretchedAmount = amount * ((finalPosition ?: 0f) - restingPosition)
|
||||
animation.animateToFinalPosition(restingPosition + stretchedAmount)
|
||||
}
|
||||
|
||||
fun updateRestingPosition(pos: Float, animated: Boolean) {
|
||||
fun updateRestingPosition(pos: Float?, animated: Boolean = true) {
|
||||
if (pos == null) return
|
||||
|
||||
restingPosition = pos
|
||||
if (animated)
|
||||
if (animated) {
|
||||
animation.animateToFinalPosition(restingPosition)
|
||||
else
|
||||
} else {
|
||||
snapTo(restingPosition)
|
||||
}
|
||||
}
|
||||
|
||||
fun cancel() = animation.cancel()
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -224,126 +305,203 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
return arrowPath
|
||||
}
|
||||
|
||||
fun addEndListener(endListener: DelayedOnAnimationEndListener): Boolean {
|
||||
return if (alphaAnimation.isRunning) {
|
||||
alphaAnimation.addEndListener(endListener)
|
||||
true
|
||||
} else if (horizontalTranslation.animation.isRunning) {
|
||||
horizontalTranslation.animation.addEndListener(endListener)
|
||||
fun addAnimationEndListener(
|
||||
animatedFloat: AnimatedFloat,
|
||||
endListener: DelayedOnAnimationEndListener
|
||||
): Boolean {
|
||||
return if (animatedFloat.isRunning) {
|
||||
animatedFloat.addEndListener(endListener)
|
||||
true
|
||||
} else {
|
||||
endListener.runNow()
|
||||
endListener.run()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelAnimations() {
|
||||
allAnimatedFloat.forEach { it.cancel() }
|
||||
}
|
||||
|
||||
fun setStretch(
|
||||
horizontalTranslationStretchAmount: Float,
|
||||
arrowStretchAmount: Float,
|
||||
backgroundWidthStretchAmount: Float,
|
||||
fullyStretchedDimens: EdgePanelParams.BackIndicatorDimens
|
||||
horizontalTranslationStretchAmount: Float,
|
||||
arrowStretchAmount: Float,
|
||||
arrowAlphaStretchAmount: Float,
|
||||
backgroundAlphaStretchAmount: Float,
|
||||
backgroundWidthStretchAmount: Float,
|
||||
backgroundHeightStretchAmount: Float,
|
||||
edgeCornerStretchAmount: Float,
|
||||
farCornerStretchAmount: Float,
|
||||
fullyStretchedDimens: EdgePanelParams.BackIndicatorDimens
|
||||
) {
|
||||
horizontalTranslation.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.horizontalTranslation,
|
||||
amount = horizontalTranslationStretchAmount
|
||||
finalPosition = fullyStretchedDimens.horizontalTranslation,
|
||||
amount = horizontalTranslationStretchAmount
|
||||
)
|
||||
arrowLength.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.arrowDimens.length,
|
||||
amount = arrowStretchAmount
|
||||
finalPosition = fullyStretchedDimens.arrowDimens.length,
|
||||
amount = arrowStretchAmount
|
||||
)
|
||||
arrowHeight.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.arrowDimens.height,
|
||||
amount = arrowStretchAmount
|
||||
finalPosition = fullyStretchedDimens.arrowDimens.height,
|
||||
amount = arrowStretchAmount
|
||||
)
|
||||
arrowAlpha.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.arrowDimens.alpha,
|
||||
amount = arrowAlphaStretchAmount
|
||||
)
|
||||
backgroundAlpha.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.alpha,
|
||||
amount = backgroundAlphaStretchAmount
|
||||
)
|
||||
backgroundWidth.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.width,
|
||||
amount = backgroundWidthStretchAmount
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.width,
|
||||
amount = backgroundWidthStretchAmount
|
||||
)
|
||||
backgroundHeight.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.height,
|
||||
amount = backgroundHeightStretchAmount
|
||||
)
|
||||
backgroundEdgeCornerRadius.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.edgeCornerRadius,
|
||||
amount = edgeCornerStretchAmount
|
||||
)
|
||||
backgroundFarCornerRadius.stretchBy(
|
||||
finalPosition = fullyStretchedDimens.backgroundDimens.farCornerRadius,
|
||||
amount = farCornerStretchAmount
|
||||
)
|
||||
}
|
||||
|
||||
fun popOffEdge(startingVelocity: Float) {
|
||||
val heightStretchAmount = startingVelocity * 50
|
||||
val widthStretchAmount = startingVelocity * 150
|
||||
val scaleStretchAmount = startingVelocity * 0.8f
|
||||
backgroundHeight.stretchTo(stretchAmount = 0f, startingVelocity = -heightStretchAmount)
|
||||
backgroundWidth.stretchTo(stretchAmount = 0f, startingVelocity = widthStretchAmount)
|
||||
scale.stretchTo(stretchAmount = 0f, startingVelocity = -scaleStretchAmount)
|
||||
}
|
||||
|
||||
fun popScale(startingVelocity: Float) {
|
||||
scalePivotX.snapTo(backgroundWidth.pos / 2)
|
||||
scale.stretchTo(stretchAmount = 0f, startingVelocity = startingVelocity)
|
||||
}
|
||||
|
||||
fun popArrowAlpha(startingVelocity: Float, springForce: SpringForce? = null) {
|
||||
arrowAlpha.stretchTo(stretchAmount = 0f, startingVelocity = startingVelocity,
|
||||
springForce = springForce)
|
||||
}
|
||||
|
||||
fun resetStretch() {
|
||||
horizontalTranslation.stretchTo(0f)
|
||||
arrowLength.stretchTo(0f)
|
||||
arrowHeight.stretchTo(0f)
|
||||
backgroundWidth.stretchTo(0f)
|
||||
backgroundHeight.stretchTo(0f)
|
||||
backgroundEdgeCornerRadius.stretchTo(0f)
|
||||
backgroundFarCornerRadius.stretchTo(0f)
|
||||
backgroundAlpha.snapTo(1f)
|
||||
verticalTranslation.snapTo(0f)
|
||||
scale.snapTo(1f)
|
||||
|
||||
horizontalTranslation.snapToRestingPosition()
|
||||
arrowLength.snapToRestingPosition()
|
||||
arrowHeight.snapToRestingPosition()
|
||||
arrowAlpha.snapToRestingPosition()
|
||||
backgroundWidth.snapToRestingPosition()
|
||||
backgroundHeight.snapToRestingPosition()
|
||||
backgroundEdgeCornerRadius.snapToRestingPosition()
|
||||
backgroundFarCornerRadius.snapToRestingPosition()
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates resting arrow and background size not accounting for stretch
|
||||
*/
|
||||
internal fun setRestingDimens(
|
||||
restingParams: EdgePanelParams.BackIndicatorDimens,
|
||||
animate: Boolean
|
||||
restingParams: EdgePanelParams.BackIndicatorDimens,
|
||||
animate: Boolean = true
|
||||
) {
|
||||
horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation, animate)
|
||||
horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation)
|
||||
scale.updateRestingPosition(restingParams.scale)
|
||||
arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha)
|
||||
backgroundAlpha.updateRestingPosition(restingParams.backgroundDimens.alpha)
|
||||
|
||||
arrowLength.updateRestingPosition(restingParams.arrowDimens.length, animate)
|
||||
arrowHeight.updateRestingPosition(restingParams.arrowDimens.height, animate)
|
||||
scalePivotX.updateRestingPosition(restingParams.backgroundDimens.width, animate)
|
||||
backgroundWidth.updateRestingPosition(restingParams.backgroundDimens.width, animate)
|
||||
backgroundHeight.updateRestingPosition(restingParams.backgroundDimens.height, animate)
|
||||
backgroundEdgeCornerRadius.updateRestingPosition(
|
||||
restingParams.backgroundDimens.edgeCornerRadius,
|
||||
animate
|
||||
restingParams.backgroundDimens.edgeCornerRadius, animate
|
||||
)
|
||||
backgroundFarCornerRadius.updateRestingPosition(
|
||||
restingParams.backgroundDimens.farCornerRadius,
|
||||
animate
|
||||
restingParams.backgroundDimens.farCornerRadius, animate
|
||||
)
|
||||
}
|
||||
|
||||
fun animateVertically(yPos: Float) = verticalTranslation.stretchTo(yPos)
|
||||
|
||||
fun setArrowStiffness(arrowStiffness: Float, arrowDampingRatio: Float) {
|
||||
arrowLength.animation.spring.apply {
|
||||
stiffness = arrowStiffness
|
||||
dampingRatio = arrowDampingRatio
|
||||
}
|
||||
arrowHeight.animation.spring.apply {
|
||||
stiffness = arrowStiffness
|
||||
dampingRatio = arrowDampingRatio
|
||||
}
|
||||
fun setSpring(
|
||||
horizontalTranslation: SpringForce? = null,
|
||||
verticalTranslation: SpringForce? = null,
|
||||
scale: SpringForce? = null,
|
||||
arrowLength: SpringForce? = null,
|
||||
arrowHeight: SpringForce? = null,
|
||||
arrowAlpha: SpringForce? = null,
|
||||
backgroundAlpha: SpringForce? = null,
|
||||
backgroundFarCornerRadius: SpringForce? = null,
|
||||
backgroundEdgeCornerRadius: SpringForce? = null,
|
||||
backgroundWidth: SpringForce? = null,
|
||||
backgroundHeight: SpringForce? = null,
|
||||
) {
|
||||
arrowLength?.let { this.arrowLength.spring = it }
|
||||
arrowHeight?.let { this.arrowHeight.spring = it }
|
||||
arrowAlpha?.let { this.arrowAlpha.spring = it }
|
||||
backgroundAlpha?.let { this.backgroundAlpha.spring = it }
|
||||
backgroundFarCornerRadius?.let { this.backgroundFarCornerRadius.spring = it }
|
||||
backgroundEdgeCornerRadius?.let { this.backgroundEdgeCornerRadius.spring = it }
|
||||
scale?.let { this.scale.spring = it }
|
||||
backgroundWidth?.let { this.backgroundWidth.spring = it }
|
||||
backgroundHeight?.let { this.backgroundHeight.spring = it }
|
||||
horizontalTranslation?.let { this.horizontalTranslation.spring = it }
|
||||
verticalTranslation?.let { this.verticalTranslation.spring = it }
|
||||
}
|
||||
|
||||
override fun hasOverlappingRendering() = false
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
var edgeCorner = backgroundEdgeCornerRadius.pos
|
||||
val edgeCorner = backgroundEdgeCornerRadius.pos
|
||||
val farCorner = backgroundFarCornerRadius.pos
|
||||
val halfHeight = backgroundHeight.pos / 2
|
||||
val canvasWidth = width
|
||||
val backgroundWidth = backgroundWidth.pos
|
||||
val scalePivotX = scalePivotX.pos
|
||||
|
||||
canvas.save()
|
||||
|
||||
if (!isLeftPanel) canvas.scale(-1f, 1f, width / 2.0f, 0f)
|
||||
if (!isLeftPanel) canvas.scale(-1f, 1f, canvasWidth / 2.0f, 0f)
|
||||
|
||||
canvas.translate(
|
||||
horizontalTranslation.pos,
|
||||
height * 0.5f + verticalTranslation.pos
|
||||
horizontalTranslation.pos,
|
||||
height * 0.5f + verticalTranslation.pos
|
||||
)
|
||||
|
||||
canvas.scale(scale.pos, scale.pos, scalePivotX, 0f)
|
||||
|
||||
val arrowBackground = arrowBackgroundRect.apply {
|
||||
left = 0f
|
||||
top = -halfHeight
|
||||
right = backgroundWidth.pos
|
||||
right = backgroundWidth
|
||||
bottom = halfHeight
|
||||
}.toPathWithRoundCorners(
|
||||
topLeft = edgeCorner,
|
||||
bottomLeft = edgeCorner,
|
||||
topRight = farCorner,
|
||||
bottomRight = farCorner
|
||||
topLeft = edgeCorner,
|
||||
bottomLeft = edgeCorner,
|
||||
topRight = farCorner,
|
||||
bottomRight = farCorner
|
||||
)
|
||||
canvas.drawPath(arrowBackground, arrowBackgroundPaint)
|
||||
canvas.drawPath(arrowBackground,
|
||||
arrowBackgroundPaint.apply { alpha = (255 * backgroundAlpha.pos).toInt() })
|
||||
|
||||
val dx = arrowLength.pos
|
||||
val dy = arrowHeight.pos
|
||||
|
||||
// How far the arrow bounding box should be from the edge of the screen. Measured from
|
||||
// either the tip or the back of the arrow, whichever is closer
|
||||
var arrowOffset = (backgroundWidth.pos - dx) / 2
|
||||
val arrowOffset = (backgroundWidth - dx) / 2
|
||||
canvas.translate(
|
||||
/* dx= */ arrowOffset,
|
||||
/* dy= */ 0f /* pass 0 for the y position since the canvas was already translated */
|
||||
/* dx= */ arrowOffset,
|
||||
/* dy= */ 0f /* pass 0 for the y position since the canvas was already translated */
|
||||
)
|
||||
|
||||
val arrowPointsAwayFromEdge = !arrowsPointLeft.xor(isLeftPanel)
|
||||
@@ -355,6 +513,8 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
}
|
||||
|
||||
val arrowPath = calculateArrowPath(dx = dx, dy = dy)
|
||||
val arrowPaint = arrowPaint
|
||||
.apply { alpha = (255 * min(arrowAlpha.pos, backgroundAlpha.pos)).toInt() }
|
||||
canvas.drawPath(arrowPath, arrowPaint)
|
||||
canvas.restore()
|
||||
|
||||
@@ -372,26 +532,17 @@ class BackPanel(context: Context, private val latencyTracker: LatencyTracker) :
|
||||
}
|
||||
|
||||
private fun RectF.toPathWithRoundCorners(
|
||||
topLeft: Float = 0f,
|
||||
topRight: Float = 0f,
|
||||
bottomRight: Float = 0f,
|
||||
bottomLeft: Float = 0f
|
||||
topLeft: Float = 0f,
|
||||
topRight: Float = 0f,
|
||||
bottomRight: Float = 0f,
|
||||
bottomLeft: Float = 0f
|
||||
): Path = Path().apply {
|
||||
val corners = floatArrayOf(
|
||||
topLeft, topLeft,
|
||||
topRight, topRight,
|
||||
bottomRight, bottomRight,
|
||||
bottomLeft, bottomLeft
|
||||
topLeft, topLeft,
|
||||
topRight, topRight,
|
||||
bottomRight, bottomRight,
|
||||
bottomLeft, bottomLeft
|
||||
)
|
||||
addRoundRect(this@toPathWithRoundCorners, corners, Path.Direction.CW)
|
||||
}
|
||||
|
||||
fun cancelAlphaAnimations() {
|
||||
alphaAnimation.cancel()
|
||||
alpha = 1f
|
||||
}
|
||||
|
||||
fun fadeOut() {
|
||||
alphaAnimation.animateToFinalPosition(0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,82 @@
|
||||
package com.android.systemui.navigationbar.gestural
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.util.TypedValue
|
||||
import androidx.core.animation.PathInterpolator
|
||||
import androidx.dynamicanimation.animation.SpringForce
|
||||
import com.android.systemui.R
|
||||
|
||||
data class EdgePanelParams(private var resources: Resources) {
|
||||
|
||||
data class ArrowDimens(
|
||||
val length: Float = 0f,
|
||||
val height: Float = 0f
|
||||
val length: Float = 0f,
|
||||
val height: Float = 0f,
|
||||
val alpha: Float = 0f,
|
||||
var alphaSpring: SpringForce? = null,
|
||||
val heightSpring: SpringForce? = null,
|
||||
val lengthSpring: SpringForce? = null,
|
||||
)
|
||||
|
||||
data class BackgroundDimens(
|
||||
val width: Float = 0f,
|
||||
val height: Float = 0f,
|
||||
val edgeCornerRadius: Float = 0f,
|
||||
val farCornerRadius: Float = 0f
|
||||
val width: Float? = 0f,
|
||||
val height: Float = 0f,
|
||||
val edgeCornerRadius: Float = 0f,
|
||||
val farCornerRadius: Float = 0f,
|
||||
val alpha: Float = 0f,
|
||||
val widthSpring: SpringForce? = null,
|
||||
val heightSpring: SpringForce? = null,
|
||||
val farCornerRadiusSpring: SpringForce? = null,
|
||||
val edgeCornerRadiusSpring: SpringForce? = null,
|
||||
val alphaSpring: SpringForce? = null,
|
||||
)
|
||||
|
||||
data class BackIndicatorDimens(
|
||||
val horizontalTranslation: Float = 0f,
|
||||
val arrowDimens: ArrowDimens = ArrowDimens(),
|
||||
val backgroundDimens: BackgroundDimens = BackgroundDimens()
|
||||
val horizontalTranslation: Float? = 0f,
|
||||
val scale: Float = 0f,
|
||||
val scalePivotX: Float = 0f,
|
||||
val arrowDimens: ArrowDimens,
|
||||
val backgroundDimens: BackgroundDimens,
|
||||
val verticalTranslationSpring: SpringForce? = null,
|
||||
val horizontalTranslationSpring: SpringForce? = null,
|
||||
val scaleSpring: SpringForce? = null,
|
||||
)
|
||||
|
||||
var arrowThickness: Float = 0f
|
||||
lateinit var entryIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var entryIndicator = BackIndicatorDimens()
|
||||
lateinit var activeIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var activeIndicator = BackIndicatorDimens()
|
||||
lateinit var cancelledIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var preThresholdIndicator = BackIndicatorDimens()
|
||||
lateinit var flungIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var fullyStretchedIndicator = BackIndicatorDimens()
|
||||
lateinit var committedIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var cancelledEdgeCornerRadius: Float = 0f
|
||||
lateinit var preThresholdIndicator: BackIndicatorDimens
|
||||
private set
|
||||
lateinit var fullyStretchedIndicator: BackIndicatorDimens
|
||||
private set
|
||||
var cancelledArrowDimens = ArrowDimens()
|
||||
|
||||
// navigation bar edge constants
|
||||
var arrowPaddingEnd: Int = 0
|
||||
private set
|
||||
var arrowThickness: Float = 0f
|
||||
private set
|
||||
lateinit var arrowStrokeAlphaSpring: Step<SpringForce>
|
||||
private set
|
||||
lateinit var arrowStrokeAlphaInterpolator: Step<Float>
|
||||
private set
|
||||
|
||||
// The closest to y
|
||||
var minArrowYPosition: Int = 0
|
||||
private set
|
||||
var fingerOffset: Int = 0
|
||||
private set
|
||||
var swipeTriggerThreshold: Float = 0f
|
||||
var staticTriggerThreshold: Float = 0f
|
||||
private set
|
||||
var reactivationTriggerThreshold: Float = 0f
|
||||
private set
|
||||
var deactivationSwipeTriggerThreshold: Float = 0f
|
||||
get() = -field
|
||||
private set
|
||||
var swipeProgressThreshold: Float = 0f
|
||||
private set
|
||||
@@ -55,6 +85,26 @@ data class EdgePanelParams(private var resources: Resources) {
|
||||
var minDeltaForSwitch: Int = 0
|
||||
private set
|
||||
|
||||
var minDragToStartAnimation: Float = 0f
|
||||
private set
|
||||
|
||||
lateinit var entryWidthInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var entryWidthTowardsEdgeInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var activeWidthInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var arrowAngleInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var translationInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var farCornerInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var edgeCornerInterpolator: PathInterpolator
|
||||
private set
|
||||
lateinit var heightInterpolator: PathInterpolator
|
||||
private set
|
||||
|
||||
init {
|
||||
update(resources)
|
||||
}
|
||||
@@ -63,6 +113,10 @@ data class EdgePanelParams(private var resources: Resources) {
|
||||
return resources.getDimension(id)
|
||||
}
|
||||
|
||||
private fun getDimenFloat(id: Int): Float {
|
||||
return TypedValue().run { resources.getValue(id, this, true); float }
|
||||
}
|
||||
|
||||
private fun getPx(id: Int): Int {
|
||||
return resources.getDimensionPixelSize(id)
|
||||
}
|
||||
@@ -73,72 +127,200 @@ data class EdgePanelParams(private var resources: Resources) {
|
||||
arrowPaddingEnd = getPx(R.dimen.navigation_edge_panel_padding)
|
||||
minArrowYPosition = getPx(R.dimen.navigation_edge_arrow_min_y)
|
||||
fingerOffset = getPx(R.dimen.navigation_edge_finger_offset)
|
||||
swipeTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
|
||||
staticTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
|
||||
reactivationTriggerThreshold =
|
||||
getDimen(R.dimen.navigation_edge_action_reactivation_drag_threshold)
|
||||
deactivationSwipeTriggerThreshold =
|
||||
getDimen(R.dimen.navigation_edge_action_deactivation_drag_threshold)
|
||||
swipeProgressThreshold = getDimen(R.dimen.navigation_edge_action_progress_threshold)
|
||||
minDeltaForSwitch = getPx(R.dimen.navigation_edge_minimum_x_delta_for_switch)
|
||||
minDragToStartAnimation =
|
||||
getDimen(R.dimen.navigation_edge_action_min_distance_to_start_animation)
|
||||
|
||||
entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
|
||||
entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
|
||||
activeWidthInterpolator = PathInterpolator(.15f, .48f, .46f, .89f)
|
||||
arrowAngleInterpolator = entryWidthInterpolator
|
||||
translationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
|
||||
farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
|
||||
edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
|
||||
heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
|
||||
|
||||
val showArrowOnProgressValue = .2f
|
||||
val showArrowOnProgressValueFactor = 1.05f
|
||||
|
||||
val entryActiveHorizontalTranslationSpring = createSpring(675f, 0.8f)
|
||||
val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
|
||||
val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
|
||||
val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
|
||||
val flungCommittedFarCornerSpring = createSpring(10000f, 1f)
|
||||
val flungCommittedWidthSpring = createSpring(10000f, 1f)
|
||||
val flungCommittedHeightSpring = createSpring(10000f, 1f)
|
||||
|
||||
entryIndicator = BackIndicatorDimens(
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
width = getDimen(R.dimen.navigation_edge_entry_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_entry_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners)
|
||||
)
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
|
||||
scale = getDimenFloat(R.dimen.navigation_edge_entry_scale),
|
||||
scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
|
||||
horizontalTranslationSpring = entryActiveHorizontalTranslationSpring,
|
||||
verticalTranslationSpring = createSpring(10000f, 0.9f),
|
||||
scaleSpring = createSpring(120f, 0.8f),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
|
||||
alpha = 0f,
|
||||
alphaSpring = createSpring(200f, 1f),
|
||||
lengthSpring = createSpring(600f, 0.4f),
|
||||
heightSpring = createSpring(600f, 0.4f),
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
alpha = 1f,
|
||||
width = getDimen(R.dimen.navigation_edge_entry_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_entry_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
|
||||
alphaSpring = createSpring(900f, 1f),
|
||||
widthSpring = createSpring(450f, 0.65f),
|
||||
heightSpring = createSpring(1500f, 0.45f),
|
||||
farCornerRadiusSpring = createSpring(300f, 0.5f),
|
||||
edgeCornerRadiusSpring = createSpring(150f, 0.5f),
|
||||
)
|
||||
)
|
||||
|
||||
activeIndicator = BackIndicatorDimens(
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_active_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_active_arrow_height),
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
width = getDimen(R.dimen.navigation_edge_active_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_active_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners)
|
||||
|
||||
)
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
|
||||
scale = getDimenFloat(R.dimen.navigation_edge_active_scale),
|
||||
horizontalTranslationSpring = entryActiveHorizontalTranslationSpring,
|
||||
scaleSpring = createSpring(450f, 0.415f),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_active_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_active_arrow_height),
|
||||
alpha = 1f,
|
||||
lengthSpring = activeCommittedArrowLengthSpring,
|
||||
heightSpring = activeCommittedArrowHeightSpring,
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
alpha = 1f,
|
||||
width = getDimen(R.dimen.navigation_edge_active_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_active_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners),
|
||||
widthSpring = createSpring(375f, 0.675f),
|
||||
heightSpring = createSpring(10000f, 1f),
|
||||
edgeCornerRadiusSpring = createSpring(600f, 0.36f),
|
||||
farCornerRadiusSpring = createSpring(2500f, 0.855f),
|
||||
)
|
||||
)
|
||||
|
||||
preThresholdIndicator = BackIndicatorDimens(
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = entryIndicator.arrowDimens.length,
|
||||
height = entryIndicator.arrowDimens.height,
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_far_corners)
|
||||
)
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
|
||||
scale = getDimenFloat(R.dimen.navigation_edge_pre_threshold_scale),
|
||||
scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
|
||||
scaleSpring = createSpring(120f, 0.8f),
|
||||
horizontalTranslationSpring = createSpring(6000f, 1f),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_height),
|
||||
alpha = 1f,
|
||||
lengthSpring = createSpring(100f, 0.6f),
|
||||
heightSpring = createSpring(100f, 0.6f),
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
alpha = 1f,
|
||||
width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
|
||||
edgeCornerRadius =
|
||||
getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
|
||||
farCornerRadius =
|
||||
getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
|
||||
widthSpring = createSpring(200f, 0.65f),
|
||||
heightSpring = createSpring(1500f, 0.45f),
|
||||
farCornerRadiusSpring = createSpring(200f, 1f),
|
||||
edgeCornerRadiusSpring = createSpring(150f, 0.5f),
|
||||
)
|
||||
)
|
||||
|
||||
committedIndicator = activeIndicator.copy(
|
||||
horizontalTranslation = null,
|
||||
arrowDimens = activeIndicator.arrowDimens.copy(
|
||||
lengthSpring = activeCommittedArrowLengthSpring,
|
||||
heightSpring = activeCommittedArrowHeightSpring,
|
||||
),
|
||||
backgroundDimens = activeIndicator.backgroundDimens.copy(
|
||||
alpha = 0f,
|
||||
// explicitly set to null to preserve previous width upon state change
|
||||
width = null,
|
||||
widthSpring = flungCommittedWidthSpring,
|
||||
heightSpring = flungCommittedHeightSpring,
|
||||
edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
|
||||
farCornerRadiusSpring = flungCommittedFarCornerSpring,
|
||||
),
|
||||
scale = 0.85f,
|
||||
scaleSpring = createSpring(650f, 1f),
|
||||
)
|
||||
|
||||
flungIndicator = committedIndicator.copy(
|
||||
arrowDimens = committedIndicator.arrowDimens.copy(
|
||||
lengthSpring = createSpring(850f, 0.46f),
|
||||
heightSpring = createSpring(850f, 0.46f),
|
||||
),
|
||||
backgroundDimens = committedIndicator.backgroundDimens.copy(
|
||||
widthSpring = flungCommittedWidthSpring,
|
||||
heightSpring = flungCommittedHeightSpring,
|
||||
edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
|
||||
farCornerRadiusSpring = flungCommittedFarCornerSpring,
|
||||
)
|
||||
)
|
||||
|
||||
cancelledIndicator = entryIndicator.copy(
|
||||
backgroundDimens = entryIndicator.backgroundDimens.copy(width = 0f)
|
||||
)
|
||||
|
||||
fullyStretchedIndicator = BackIndicatorDimens(
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
width = getDimen(R.dimen.navigation_edge_stretch_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_stretch_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners)
|
||||
horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
|
||||
scale = getDimenFloat(R.dimen.navigation_edge_stretch_scale),
|
||||
horizontalTranslationSpring = null,
|
||||
verticalTranslationSpring = null,
|
||||
scaleSpring = null,
|
||||
arrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
|
||||
alpha = 1f,
|
||||
alphaSpring = null,
|
||||
heightSpring = null,
|
||||
lengthSpring = null,
|
||||
),
|
||||
backgroundDimens = BackgroundDimens(
|
||||
alpha = 1f,
|
||||
width = getDimen(R.dimen.navigation_edge_stretch_background_width),
|
||||
height = getDimen(R.dimen.navigation_edge_stretch_background_height),
|
||||
edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
|
||||
farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners),
|
||||
alphaSpring = null,
|
||||
widthSpring = null,
|
||||
heightSpring = null,
|
||||
edgeCornerRadiusSpring = null,
|
||||
farCornerRadiusSpring = null,
|
||||
)
|
||||
)
|
||||
|
||||
arrowStrokeAlphaInterpolator = Step(
|
||||
threshold = showArrowOnProgressValue,
|
||||
factor = showArrowOnProgressValueFactor,
|
||||
postThreshold = 1f,
|
||||
preThreshold = 0f
|
||||
)
|
||||
|
||||
entryIndicator.arrowDimens.alphaSpring?.let { alphaSpring ->
|
||||
arrowStrokeAlphaSpring = Step(
|
||||
threshold = showArrowOnProgressValue,
|
||||
factor = showArrowOnProgressValueFactor,
|
||||
postThreshold = alphaSpring,
|
||||
preThreshold = SpringForce().setStiffness(2000f).setDampingRatio(1f)
|
||||
)
|
||||
)
|
||||
|
||||
cancelledEdgeCornerRadius = getDimen(R.dimen.navigation_edge_cancelled_edge_corners)
|
||||
|
||||
cancelledArrowDimens = ArrowDimens(
|
||||
length = getDimen(R.dimen.navigation_edge_cancelled_arrow_length),
|
||||
height = getDimen(R.dimen.navigation_edge_cancelled_arrow_height)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createSpring(stiffness: Float, dampingRatio: Float): SpringForce {
|
||||
return SpringForce().setStiffness(stiffness).setDampingRatio(dampingRatio)
|
||||
}
|
||||
Reference in New Issue
Block a user