refactor: replaced bottom actions list with floating action button

This commit is contained in:
2026-06-23 11:53:30 +03:00
parent 3cf6b876f9
commit 13d6ba0b52
4 changed files with 103 additions and 93 deletions
@@ -3,6 +3,12 @@ package ru.omni_devel.cards
import android.content.Intent
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalActivity
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -29,9 +35,12 @@ import androidx.compose.material3.DrawerValue
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.QrCode
import androidx.compose.material.icons.outlined.DensityMedium
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
@@ -50,6 +59,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -60,80 +70,76 @@ import androidx.core.graphics.toColorInt
import kotlinx.coroutines.launch
@Composable
fun Page(name: String, innerPadding: PaddingValues, pages: List<NavigationPageData>? = null, content: @Composable () -> Unit) {
val activityContext = LocalActivity.current
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
BackHandler(
enabled = pages != null && drawerState.isOpen
) {
scope.launch {
drawerState.close()
fun Page(
name: String,
innerPadding: PaddingValues,
floatingActionButton: @Composable (() -> Unit) = {},
content: @Composable () -> Unit
) {
Scaffold(
floatingActionButton = floatingActionButton
) { padding ->
Box(
modifier = Modifier
.padding(padding)
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.padding(horizontal = 16.dp)
.padding(top = 16.dp)
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
content()
}
}
}
}
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
if (pages != null) {
ModalDrawerSheet(
modifier = Modifier.background(MaterialTheme.colorScheme.background).padding(8.dp)
) {
for (page in pages) {
NavigationDrawerItem(
label = { Text(page.name) },
selected = false,
onClick = {
scope.launch { drawerState.close() }
@Composable
fun ExpandableFab(
items: List<NavigationPageData>
) {
val activityContext = LocalActivity.current
var isExpanded by remember { mutableStateOf(false) }
if (page.pageClass != null) {
val intent = Intent(activityContext, page.pageClass)
val rotation by animateFloatAsState(if (isExpanded) 45f else 0f)
activityContext!!.startActivity(intent)
} else if (page.onClick != null) {
page.onClick()
}
}
)
Column(
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items.forEach { page ->
AnimatedVisibility(
visible = isExpanded,
enter = fadeIn() + scaleIn(),
exit = fadeOut() + scaleOut()
) {
ExtendedFloatingActionButton(
text = { Text(page.name) },
icon = { Icon(page.icon, contentDescription = null) },
onClick = {
isExpanded = false
if (page.pageClass != null) {
val intent = Intent(activityContext, page.pageClass)
activityContext!!.startActivity(intent)
} else if (page.onClick != null) {
page.onClick()
}
}
}
)
}
}
) {
Scaffold(
topBar = {
TopBar(name, innerPadding, if (pages != null) {
{
Icon(
modifier = Modifier.clickable() {
scope.launch {
drawerState.open()
}
},
imageVector = Icons.Outlined.DensityMedium,
contentDescription = null,
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
} else null)
}
) { padding ->
Box(
modifier = Modifier
.padding(padding)
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.padding(horizontal = 16.dp)
.padding(top = 16.dp)
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
content()
}
}
FloatingActionButton(
onClick = { isExpanded = !isExpanded }
) {
Icon(
modifier = Modifier.graphicsLayer { rotationZ = rotation },
imageVector = Icons.Outlined.Add,
contentDescription = null
)
}
}
}