Anonymous
JetPack Compose: Как создать Fab с несколькими элементами с анимацией?
Сообщение
Anonymous » 11 июн 2025, 20:06
Я пытаюсь создать многоэлементную кнопку плавающего действия со следующей анимацией:
Я создал многоэтажную кнопку плавающего действия, но я не смог реализовать анимацию. Filterfabmenubutton Composable, который я показываю в качестве пункта меню: < /p>
Код: Выделить всё
@Composable
fun FilterFabMenuButton(
item: FilterFabMenuItem,
onClick: (FilterFabMenuItem) -> Unit,
modifier: Modifier = Modifier
) {
FloatingActionButton(
modifier = modifier,
onClick = {
onClick(item)
},
backgroundColor = colorResource(
id = R.color.primary_color
)
) {
Icon(
painter = painterResource(item.icon), contentDescription = null, tint = colorResource(
id = R.color.white
)
)
}
}
< /code>
У меня есть Composable Filterfabmenulabel, которая является меткой для FilterFabMenubutton: < /p>
FilterFabMenuLabel
Код: Выделить всё
@Composable
fun FilterFabMenuLabel(
label: String,
modifier: Modifier = Modifier
) {
Surface(
modifier = modifier,
shape = RoundedCornerShape(6.dp),
color = Color.Black.copy(alpha = 0.8f)
) {
Text(
text = label, color = Color.White,
modifier = Modifier.padding(horizontal = 20.dp, vertical = 2.dp),
fontSize = 14.sp,
maxLines = 1
)
}
}
< /code>
Я имею Composable filterfabmenuitem, которая является строкой, которая содержит Composables filterfabmenulabel и filterfabmenubutton: < /p>
FilterFabMenuItem
Код: Выделить всё
@Composable
fun FilterFabMenuItem(
menuItem: FilterFabMenuItem,
onMenuItemClick: (FilterFabMenuItem) -> Unit,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
//label
FilterFabMenuLabel(label = menuItem.label)
//fab
FilterFabMenuButton(item = menuItem, onClick = onMenuItemClick)
}
}
< /code>
У меня есть Composable Filterfabmenu, который является столбцом, в котором показаны элементы меню: < /p>
FilterFabMenu
Код: Выделить всё
@Composable
fun FilterFabMenu(
visible: Boolean,
items: List,
modifier: Modifier = Modifier
) {
val enterTransition = remember {
expandVertically(
expandFrom = Alignment.Bottom,
animationSpec = tween(150, easing = FastOutSlowInEasing)
) + fadeIn(
initialAlpha = 0.3f,
animationSpec = tween(150, easing = FastOutSlowInEasing)
)
}
val exitTransition = remember {
shrinkVertically(
shrinkTowards = Alignment.Bottom,
animationSpec = tween(150, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(150, easing = FastOutSlowInEasing)
)
}
AnimatedVisibility(visible = visible, enter = enterTransition, exit = exitTransition) {
Column(
modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
items.forEach { menuItem ->
FilterFabMenuItem(
menuItem = menuItem,
onMenuItemClick = {}
)
}
}
}
}
Я имею композицию Filterfab, который расширяет/обрушивает Filtermenu:
Код: Выделить всё
@Composable
fun FilterFab(
state: FilterFabState,
rotation:Float,
onClick: (FilterFabState) -> Unit,
modifier: Modifier = Modifier
) {
FloatingActionButton(
modifier = modifier
.rotate(rotation),
elevation = FloatingActionButtonDefaults.elevation(defaultElevation = 0.dp),
onClick = {
onClick(
if (state == FilterFabState.EXPANDED) {
FilterFabState.COLLAPSED
} else {
FilterFabState.EXPANDED
}
)
},
backgroundColor = colorResource(
R.color.primary_color
),
shape = CircleShape
) {
Icon(
painter = painterResource(R.drawable.fab_add),
contentDescription = null,
tint = Color.White
)
}
}
< /code>
Последнее, но не менее важное, у меня есть композитный фильтр, который является столбцом, который содержит композиции Filterfabmenu и Filterfab: < /p>
FilterView
Код: Выделить всё
@SuppressLint("UnusedTransitionTargetStateParameter")
@Composable
fun FilterView(
items: List,
modifier: Modifier = Modifier
) {
var filterFabState by rememberSaveable() {
mutableStateOf(FilterFabState.COLLAPSED)
}
val transitionState = remember {
MutableTransitionState(filterFabState).apply {
targetState = FilterFabState.COLLAPSED
}
}
val transition = updateTransition(targetState = transitionState, label = "transition")
val iconRotationDegree by transition.animateFloat({
tween(durationMillis = 150, easing = FastOutSlowInEasing)
}, label = "rotation") {
if (filterFabState == FilterFabState.EXPANDED) 230f else 0f
}
Column(
modifier = modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(16.dp,Alignment.Bottom)
) {
FilterFabMenu(items = items, visible = filterFabState == FilterFabState.EXPANDED)
FilterFab(
state = filterFabState,
rotation = iconRotationDegree, onClick = { state ->
filterFabState = state
})
}
}
Это дает следующий результат:
Подробнее здесь:
https://stackoverflow.com/questions/753 ... -animation
1749661617
Anonymous
Я пытаюсь создать многоэлементную кнопку плавающего действия со следующей анимацией: Я создал многоэтажную кнопку плавающего действия, но я не смог реализовать анимацию. Filterfabmenubutton Composable, который я показываю в качестве пункта меню: < /p> [code]FilterFabMenuButton[/code] [code]@Composable fun FilterFabMenuButton( item: FilterFabMenuItem, onClick: (FilterFabMenuItem) -> Unit, modifier: Modifier = Modifier ) { FloatingActionButton( modifier = modifier, onClick = { onClick(item) }, backgroundColor = colorResource( id = R.color.primary_color ) ) { Icon( painter = painterResource(item.icon), contentDescription = null, tint = colorResource( id = R.color.white ) ) } } < /code> У меня есть Composable Filterfabmenulabel, которая является меткой для FilterFabMenubutton: < /p> FilterFabMenuLabel[/code] [code]@Composable fun FilterFabMenuLabel( label: String, modifier: Modifier = Modifier ) { Surface( modifier = modifier, shape = RoundedCornerShape(6.dp), color = Color.Black.copy(alpha = 0.8f) ) { Text( text = label, color = Color.White, modifier = Modifier.padding(horizontal = 20.dp, vertical = 2.dp), fontSize = 14.sp, maxLines = 1 ) } } < /code> Я имею Composable filterfabmenuitem, которая является строкой, которая содержит Composables filterfabmenulabel и filterfabmenubutton: < /p> FilterFabMenuItem[/code] [code]@Composable fun FilterFabMenuItem( menuItem: FilterFabMenuItem, onMenuItemClick: (FilterFabMenuItem) -> Unit, modifier: Modifier = Modifier ) { Row( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically ) { //label FilterFabMenuLabel(label = menuItem.label) //fab FilterFabMenuButton(item = menuItem, onClick = onMenuItemClick) } } < /code> У меня есть Composable Filterfabmenu, который является столбцом, в котором показаны элементы меню: < /p> FilterFabMenu[/code] [code]@Composable fun FilterFabMenu( visible: Boolean, items: List, modifier: Modifier = Modifier ) { val enterTransition = remember { expandVertically( expandFrom = Alignment.Bottom, animationSpec = tween(150, easing = FastOutSlowInEasing) ) + fadeIn( initialAlpha = 0.3f, animationSpec = tween(150, easing = FastOutSlowInEasing) ) } val exitTransition = remember { shrinkVertically( shrinkTowards = Alignment.Bottom, animationSpec = tween(150, easing = FastOutSlowInEasing) ) + fadeOut( animationSpec = tween(150, easing = FastOutSlowInEasing) ) } AnimatedVisibility(visible = visible, enter = enterTransition, exit = exitTransition) { Column( modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy(16.dp), ) { items.forEach { menuItem -> FilterFabMenuItem( menuItem = menuItem, onMenuItemClick = {} ) } } } } [/code] Я имею композицию Filterfab, который расширяет/обрушивает Filtermenu: [code]FilterFab[/code] [code]@Composable fun FilterFab( state: FilterFabState, rotation:Float, onClick: (FilterFabState) -> Unit, modifier: Modifier = Modifier ) { FloatingActionButton( modifier = modifier .rotate(rotation), elevation = FloatingActionButtonDefaults.elevation(defaultElevation = 0.dp), onClick = { onClick( if (state == FilterFabState.EXPANDED) { FilterFabState.COLLAPSED } else { FilterFabState.EXPANDED } ) }, backgroundColor = colorResource( R.color.primary_color ), shape = CircleShape ) { Icon( painter = painterResource(R.drawable.fab_add), contentDescription = null, tint = Color.White ) } } < /code> Последнее, но не менее важное, у меня есть композитный фильтр, который является столбцом, который содержит композиции Filterfabmenu и Filterfab: < /p> FilterView[/code] [code]@SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun FilterView( items: List, modifier: Modifier = Modifier ) { var filterFabState by rememberSaveable() { mutableStateOf(FilterFabState.COLLAPSED) } val transitionState = remember { MutableTransitionState(filterFabState).apply { targetState = FilterFabState.COLLAPSED } } val transition = updateTransition(targetState = transitionState, label = "transition") val iconRotationDegree by transition.animateFloat({ tween(durationMillis = 150, easing = FastOutSlowInEasing) }, label = "rotation") { if (filterFabState == FilterFabState.EXPANDED) 230f else 0f } Column( modifier = modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy(16.dp,Alignment.Bottom) ) { FilterFabMenu(items = items, visible = filterFabState == FilterFabState.EXPANDED) FilterFab( state = filterFabState, rotation = iconRotationDegree, onClick = { state -> filterFabState = state }) } } [/code] Это дает следующий результат: Подробнее здесь: [url]https://stackoverflow.com/questions/75346725/jetpack-compose-how-to-create-multi-item-fab-with-animation[/url]