Floating Action Button with Material Animations
Author: Johan Reitan
Floating Action Button with animations that are implemented as per the Material Design spec.
import androidx.compose.animation.AnimatedVisibility | |
import androidx.compose.animation.EnterExitState | |
import androidx.compose.animation.EnterTransition | |
import androidx.compose.animation.ExitTransition | |
import androidx.compose.animation.core.FastOutLinearInEasing | |
import androidx.compose.animation.core.LinearEasing | |
import androidx.compose.animation.core.LinearOutSlowInEasing | |
import androidx.compose.animation.core.animateFloat | |
import androidx.compose.animation.core.tween | |
import androidx.compose.animation.fadeIn | |
import androidx.compose.animation.fadeOut | |
import androidx.compose.foundation.interaction.MutableInteractionSource | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.shape.CornerSize | |
import androidx.compose.material.FloatingActionButtonDefaults | |
import androidx.compose.material.FloatingActionButtonElevation | |
import androidx.compose.material.MaterialTheme | |
import androidx.compose.material.contentColorFor | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.remember | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.graphics.Shape | |
import androidx.compose.ui.graphics.graphicsLayer | |
import androidx.compose.material.FloatingActionButton as MaterialFloatingActionButton | |
/** | |
* FAB with show/hide animations according to the Material spec | |
*/ | |
@Composable | |
fun FloatingActionButton( | |
onClick: () -> Unit, | |
modifier: Modifier = Modifier, | |
visible: Boolean = true, | |
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, | |
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)), | |
backgroundColor: Color = MaterialTheme.colors.secondary, | |
contentColor: Color = contentColorFor(backgroundColor), | |
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(), | |
content: @Composable () -> Unit, | |
) { | |
AnimatedVisibility( | |
modifier = modifier, | |
visible = visible, | |
enter = fadeIn( | |
animationSpec = tween( | |
durationMillis = 15, | |
delayMillis = 30, | |
easing = LinearEasing, | |
), | |
), | |
exit = fadeOut( | |
animationSpec = tween( | |
durationMillis = 15, | |
delayMillis = 150, | |
easing = LinearEasing, | |
) | |
), | |
) { | |
val fabScale by transition.animateFloat( | |
transitionSpec = { | |
tween( | |
durationMillis = when (targetState) { | |
EnterExitState.PreEnter, | |
EnterExitState.Visible, | |
-> 330 | |
EnterExitState.PostExit -> 135 | |
}, | |
delayMillis = 0, | |
easing = LinearOutSlowInEasing, | |
) | |
}, | |
label = "FAB scale" | |
) { | |
when (it) { | |
EnterExitState.PreEnter, | |
EnterExitState.PostExit, | |
-> 0f | |
EnterExitState.Visible -> 1f | |
} | |
} | |
MaterialFloatingActionButton( | |
modifier = Modifier.graphicsLayer { | |
scaleX = fabScale | |
scaleY = fabScale | |
}, | |
onClick = onClick, | |
interactionSource = interactionSource, | |
shape = shape, | |
backgroundColor = backgroundColor, | |
contentColor = contentColor, | |
elevation = elevation, | |
) { | |
val contentScale by transition.animateFloat( | |
transitionSpec = { | |
tween( | |
durationMillis = when (targetState) { | |
EnterExitState.PreEnter, | |
EnterExitState.Visible, | |
-> 240 | |
EnterExitState.PostExit -> 135 | |
}, | |
delayMillis = when (targetState) { | |
EnterExitState.PreEnter, | |
EnterExitState.Visible, | |
-> 90 | |
EnterExitState.PostExit -> 0 | |
}, | |
easing = FastOutLinearInEasing, | |
) | |
}, | |
label = "FAB content scale" | |
) { | |
when (it) { | |
EnterExitState.PreEnter, | |
EnterExitState.PostExit, | |
-> 0f | |
EnterExitState.Visible -> 1f | |
} | |
} | |
Box( | |
Modifier.graphicsLayer { | |
scaleX = contentScale | |
scaleY = contentScale | |
} | |
) { | |
content() | |
} | |
} | |
} | |
} |
Have a project you'd like to submit? Fill this form, will ya!
If you like this snippet, you might also like:
Maker OS is an all-in-one productivity system for developers
I built Maker OS to track, manage & organize my life. Now you can do it too!