Restore secondary FAB fade

This commit is contained in:
FooIbar committed 2023-11-21 16:53:49 +08:00
1 parent b49a80bb35
commit 8dc3b1f376
4 files changed
+38 -13

No files matched your search

@@ -10,7 +10,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.SmallFloatingActionButton
@@ -22,6 +22,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.vector.ImageVector
@@ -50,6 +51,10 @@ class FabLayout @JvmOverloads constructor(
var expanded by mutableStateOf(false)
private val listeners = mutableListOf<OnExpandStateListener>()
private var mHidden by mutableStateOf(hidden)
private var mExpanded by mutableStateOf(expanded)
private var showPrimaryFab by mutableStateOf(true)
fun addOnExpandStateListener(listener: OnExpandStateListener) {
listeners.add(listener)
}
@@ -63,6 +68,12 @@ class FabLayout @JvmOverloads constructor(
hidden = true
}
fun hidePrimaryFab() {
mHidden = true
showPrimaryFab = false
hide()
}
@Composable
override fun Content() {
Mdc3Theme {
@@ -86,23 +97,31 @@ class FabLayout @JvmOverloads constructor(
val coroutineScope = rememberCoroutineScope()
val appearState by animateFloatAsState(
targetValue = if (hidden) 0f else 1f,
animationSpec = tween(FAB_ANIMATE_TIME),
animationSpec = tween(FAB_ANIMATE_TIME, if (mExpanded) FAB_ANIMATE_TIME else 0),
label = "hiddenState",
)
) { mHidden = hidden }
Box(
modifier = Modifier.fillMaxSize().padding(16.dp),
contentAlignment = Alignment.BottomEnd,
) {
Box(contentAlignment = Alignment.Center) {
val animatedProgress by animateFloatMergePredictiveBackAsState(expanded) { expanded = false }
val animatedProgress by animateFloatMergePredictiveBackAsState(
enable = expanded,
animationSpec = tween(FAB_ANIMATE_TIME, if (mHidden) FAB_ANIMATE_TIME else 0),
finishedListener = { mExpanded = expanded },
) { expanded = false }
FloatingActionButton(
onClick = { expanded = !expanded },
modifier = Modifier.rotate(lerp(-90f, 0f, appearState)).scale(appearState),
) {
Icon(
imageVector = Icons.Default.Add,
imageVector = Icons.Default.Close,
contentDescription = null,
modifier = Modifier.rotate(lerp(135f, 0f, animatedProgress)),
modifier = if (showPrimaryFab) {
Modifier.rotate(lerp(0f, -135f, animatedProgress))
} else {
Modifier
},
)
}
secondaryFab?.run {
@@ -122,7 +141,7 @@ class FabLayout @JvmOverloads constructor(
val distance = lerp(150 * (size - index) + 50, 0, animatedProgress)
placeable.placeRelative(0, -distance, -(size - index).toFloat())
}
}.rotate(lerp(90f, 0f, appearState)).scale(appearState),
}.alpha(1 - animatedProgress),
) {
Icon(imageVector = imageVector, contentDescription = null)
}
@@ -9,7 +9,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.SmallFloatingActionButton
@@ -19,6 +19,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.vector.ImageVector
@@ -72,15 +73,18 @@ fun FabLayout(
contentAlignment = Alignment.BottomEnd,
) {
Box(contentAlignment = Alignment.Center) {
val animatedProgress by animateFloatMergePredictiveBackAsState(expanded) { onExpandChanged(false) }
val animatedProgress by animateFloatMergePredictiveBackAsState(
enable = expanded,
animationSpec = tween(FAB_ANIMATE_TIME),
) { onExpandChanged(false) }
FloatingActionButton(
onClick = { onExpandChanged(!expanded) },
modifier = Modifier.rotate(lerp(-90f, 0f, appearState)).scale(appearState),
) {
Icon(
imageVector = Icons.Default.Add,
imageVector = Icons.Default.Close,
contentDescription = null,
modifier = Modifier.rotate(lerp(135f, 0f, animatedProgress)),
modifier = Modifier.rotate(lerp(0f, -135f, animatedProgress)),
)
}
secondaryFab.run {
@@ -100,7 +104,7 @@ fun FabLayout(
val distance = lerp(150 * (size - index) + 50, 0, animatedProgress)
placeable.placeRelative(0, -distance, -(size - index).toFloat())
}
}.rotate(lerp(90f, 0f, appearState)).scale(appearState),
}.alpha(1 - animatedProgress),
) {
Icon(imageVector = imageVector, contentDescription = null)
}
@@ -351,7 +351,7 @@ class DownloadsScene : SearchBarScene() {
fastScroller.setHandlerDrawable(handlerDrawable)
with(fabLayout) {
autoCancel = false
hide()
hidePrimaryFab()
addOnExpandStateListener { if (!it && tracker.isInCustomChoice) tracker.clearSelection() }
secondaryFab = listOf(
Icons.Default.DoneAll to {
@@ -31,6 +31,7 @@ import kotlinx.coroutines.CancellationException
fun animateFloatMergePredictiveBackAsState(
enable: Boolean,
animationSpec: AnimationSpec<Float> = spring(),
finishedListener: ((Float) -> Unit)? = null,
onBack: () -> Unit,
): State<Float> {
// Natural animator state correspond with principal value
@@ -38,6 +39,7 @@ fun animateFloatMergePredictiveBackAsState(
targetValue = if (enable) 0f else 1f,
animationSpec = animationSpec,
label = "animationProgress",
finishedListener = finishedListener,
)
// User predictive back animation progress holder && value correspond with UI State
val ret = remember { mutableFloatStateOf(1F) }