fix: FAB 在切换页面时文字溢出
This commit is contained in:
parent
0fb4192493
commit
7fa618a611
5 changed files with 55 additions and 96 deletions
|
|
@ -37,7 +37,7 @@ android {
|
||||||
applicationId = "cn.super12138.todo"
|
applicationId = "cn.super12138.todo"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 791
|
versionCode = 883
|
||||||
versionName = "2.3.3"
|
versionName = "2.3.3"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,29 @@
|
||||||
package cn.super12138.todo.ui.components
|
package cn.super12138.todo.ui.components
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.FloatingActionButtonDefaults
|
import androidx.compose.material3.FloatingActionButtonDefaults
|
||||||
import androidx.compose.material3.FloatingActionButtonElevation
|
import androidx.compose.material3.FloatingActionButtonElevation
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.SmallExtendedFloatingActionButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.contentColorFor
|
import androidx.compose.material3.contentColorFor
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import cn.super12138.todo.utils.VibrationUtils
|
import cn.super12138.todo.utils.VibrationUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 带动画且比 Material 3 内置组件动画好看的的可扩展 FAB
|
* 封装的内置组件 FAB,在点击时支持添加震动反馈
|
||||||
* * (内置组件的动画总是卡一下。。。)
|
* * (现在内置组件的动画好像好一点了)
|
||||||
*
|
*
|
||||||
* 将缩放部分转为最简单的`AnimatedVisibility`实现
|
* 将缩放部分转为最简单的`AnimatedVisibility`实现
|
||||||
* @param icon FAB 的前置图标
|
* @param icon FAB 的前置图标
|
||||||
* @param text FAB 的文本
|
* @param text FAB 的文本
|
||||||
* @param textOverflow FAB 文本溢出显示方案
|
|
||||||
* @param expanded 是否为展开状态
|
* @param expanded 是否为展开状态
|
||||||
* @param containerColor FAB 容器的颜色
|
* @param containerColor FAB 容器的颜色
|
||||||
* @param contentColor FAB 文本和图标颜色,通常不需要自己指定,会自动依据容器颜色设置
|
* @param contentColor FAB 文本和图标颜色,通常不需要自己指定,会自动依据容器颜色设置
|
||||||
|
|
@ -36,20 +31,34 @@ import cn.super12138.todo.utils.VibrationUtils
|
||||||
* @param onClick 点击 FAB 后的回调
|
* @param onClick 点击 FAB 后的回调
|
||||||
* @param modifier `Modifier` 修改器
|
* @param modifier `Modifier` 修改器
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AnimatedExtendedFloatingActionButton(
|
fun TodoFloatingActionButton(
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
icon: ImageVector,
|
|
||||||
text: String,
|
text: String,
|
||||||
textOverflow: TextOverflow = TextOverflow.Clip,
|
icon: ImageVector,
|
||||||
expanded: Boolean,
|
onClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
expanded: Boolean = true,
|
||||||
|
shape: Shape = FloatingActionButtonDefaults.smallExtendedFabShape,
|
||||||
containerColor: Color = FloatingActionButtonDefaults.containerColor,
|
containerColor: Color = FloatingActionButtonDefaults.containerColor,
|
||||||
contentColor: Color = contentColorFor(containerColor),
|
contentColor: Color = contentColorFor(containerColor),
|
||||||
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
|
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
|
||||||
onClick: () -> Unit
|
interactionSource: MutableInteractionSource? = null,
|
||||||
) {
|
) {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
FloatingActionButton(
|
SmallExtendedFloatingActionButton(
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
overflow = TextOverflow.Clip
|
||||||
|
)
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
VibrationUtils.performHapticFeedback(view)
|
VibrationUtils.performHapticFeedback(view)
|
||||||
onClick()
|
onClick()
|
||||||
|
|
@ -57,27 +66,8 @@ fun AnimatedExtendedFloatingActionButton(
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
containerColor = containerColor,
|
containerColor = containerColor,
|
||||||
contentColor = contentColor,
|
contentColor = contentColor,
|
||||||
|
shape = shape,
|
||||||
|
interactionSource = interactionSource,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
)
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = icon,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
// Spacer(Modifier.width(if (expanded) 8.dp else 0.dp))
|
|
||||||
AnimatedVisibility(expanded) {
|
|
||||||
Row {
|
|
||||||
Spacer(Modifier.width(8.dp))
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = textOverflow
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -23,9 +23,7 @@ import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material.icons.outlined.Save
|
import androidx.compose.material.icons.outlined.Save
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SmallExtendedFloatingActionButton
|
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
|
@ -51,6 +49,7 @@ import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.components.ChipItem
|
import cn.super12138.todo.ui.components.ChipItem
|
||||||
import cn.super12138.todo.ui.components.ConfirmDialog
|
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
||||||
|
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryChip
|
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryChip
|
||||||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryTextField
|
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryTextField
|
||||||
import cn.super12138.todo.ui.pages.editor.components.TodoContentTextField
|
import cn.super12138.todo.ui.pages.editor.components.TodoContentTextField
|
||||||
|
|
@ -115,41 +114,33 @@ fun TodoEditorPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BackHandler { checkModifiedBeforeBack() }
|
BackHandler(onBack = ::checkModifiedBeforeBack)
|
||||||
|
|
||||||
LargeTopAppBarScaffold(
|
LargeTopAppBarScaffold(
|
||||||
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
with(sharedTransitionScope) {
|
with(sharedTransitionScope) {
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
|
modifier = Modifier.imePadding()
|
||||||
|
) {
|
||||||
if (toDo !== null) {
|
if (toDo !== null) {
|
||||||
SmallExtendedFloatingActionButton(
|
TodoFloatingActionButton(
|
||||||
text = { Text(stringResource(R.string.action_delete)) },
|
text = stringResource(R.string.action_delete),
|
||||||
icon = {
|
icon = Icons.Outlined.Delete,
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.Delete,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
expanded = true,
|
expanded = true,
|
||||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
onClick = { uiState.showDeleteConfirmDialog = true },
|
onClick = { uiState.showDeleteConfirmDialog = true }
|
||||||
modifier = Modifier.imePadding()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SmallExtendedFloatingActionButton(
|
TodoFloatingActionButton(
|
||||||
text = { Text(stringResource(R.string.action_save)) },
|
text = stringResource(R.string.action_save),
|
||||||
icon = {
|
icon = Icons.Outlined.Save,
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.Save,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
expanded = true,
|
expanded = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (uiState.setErrorIfNotValid()) {
|
if (uiState.setErrorIfNotValid()) {
|
||||||
return@SmallExtendedFloatingActionButton
|
return@TodoFloatingActionButton
|
||||||
} else {
|
} else {
|
||||||
uiState.clearError()
|
uiState.clearError()
|
||||||
val newTodo = TodoEntity(
|
val newTodo = TodoEntity(
|
||||||
|
|
@ -163,7 +154,6 @@ fun TodoEditorPage(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.imePadding()
|
|
||||||
.sharedElement(
|
.sharedElement(
|
||||||
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
||||||
animatedVisibilityScope = animatedVisibilityScope
|
animatedVisibilityScope = animatedVisibilityScope
|
||||||
|
|
@ -172,7 +162,7 @@ fun TodoEditorPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBack = { checkModifiedBeforeBack() },
|
onBack = ::checkModifiedBeforeBack,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
|
@ -183,19 +173,12 @@ fun TodoEditorPage(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
// with(sharedTransitionScope) {
|
|
||||||
TodoContentTextField(
|
TodoContentTextField(
|
||||||
value = uiState.toDoContent,
|
value = uiState.toDoContent,
|
||||||
onValueChange = { uiState.toDoContent = it },
|
onValueChange = { uiState.toDoContent = it },
|
||||||
isError = uiState.isErrorContent,
|
isError = uiState.isErrorContent,
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
/*.sharedBounds(
|
|
||||||
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CONTENT_TRANSITION}_${toDo?.id}"),
|
|
||||||
animatedVisibilityScope = animatedVisibilityScope
|
|
||||||
)*/
|
|
||||||
)
|
)
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
@ -217,20 +200,13 @@ fun TodoEditorPage(
|
||||||
enter = fadeIn() + expandVertically(),
|
enter = fadeIn() + expandVertically(),
|
||||||
exit = fadeOut() + shrinkVertically()
|
exit = fadeOut() + shrinkVertically()
|
||||||
) {
|
) {
|
||||||
// with(sharedTransitionScope) {
|
|
||||||
TodoCategoryTextField(
|
TodoCategoryTextField(
|
||||||
value = uiState.categoryContent,
|
value = uiState.categoryContent,
|
||||||
onValueChange = { uiState.categoryContent = it },
|
onValueChange = { uiState.categoryContent = it },
|
||||||
isError = uiState.isErrorCategory,
|
isError = uiState.isErrorCategory,
|
||||||
supportingText = stringResource(uiState.categorySupportingText),
|
supportingText = stringResource(uiState.categorySupportingText),
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
/*.sharedBounds(
|
|
||||||
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CATEGORY_TRANSITION}_${toDo?.id}"),
|
|
||||||
animatedVisibilityScope = animatedVisibilityScope
|
|
||||||
)*/
|
|
||||||
)
|
)
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Add
|
import androidx.compose.material.icons.outlined.Add
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SmallExtendedFloatingActionButton
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
||||||
import androidx.compose.material3.animateFloatingActionButton
|
import androidx.compose.material3.animateFloatingActionButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -37,6 +34,7 @@ import cn.super12138.todo.constants.Constants
|
||||||
import cn.super12138.todo.logic.database.TodoEntity
|
import cn.super12138.todo.logic.database.TodoEntity
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.ui.components.ConfirmDialog
|
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||||
|
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||||
import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar
|
import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar
|
||||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||||
|
|
||||||
|
|
@ -84,14 +82,9 @@ fun MainPage(
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
with(sharedTransitionScope) {
|
with(sharedTransitionScope) {
|
||||||
SmallExtendedFloatingActionButton(
|
TodoFloatingActionButton(
|
||||||
text = { Text(stringResource(R.string.action_add_task)) },
|
text = stringResource(R.string.action_add_task),
|
||||||
icon = {
|
icon = Icons.Outlined.Add,
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.Add,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
expanded = expandedFab,
|
expanded = expandedFab,
|
||||||
onClick = { toTodoEditPage(null) },
|
onClick = { toTodoEditPage(null) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.ui.components.AnimatedExtendedFloatingActionButton
|
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
||||||
|
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||||
import cn.super12138.todo.ui.pages.settings.components.category.CategoryItem
|
import cn.super12138.todo.ui.pages.settings.components.category.CategoryItem
|
||||||
import cn.super12138.todo.ui.pages.settings.components.category.CategoryPromptDialog
|
import cn.super12138.todo.ui.pages.settings.components.category.CategoryPromptDialog
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -65,7 +65,7 @@ fun SettingsDataCategory(
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
AnimatedExtendedFloatingActionButton(
|
TodoFloatingActionButton(
|
||||||
icon = Icons.Outlined.Add,
|
icon = Icons.Outlined.Add,
|
||||||
text = stringResource(R.string.action_add_category),
|
text = stringResource(R.string.action_add_category),
|
||||||
expanded = isExpanded,
|
expanded = isExpanded,
|
||||||
|
|
@ -81,7 +81,7 @@ fun SettingsDataCategory(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(innerPadding)
|
.padding(innerPadding) //TODO: 可能需要清除屏幕边距
|
||||||
) {
|
) {
|
||||||
if (categories.isEmpty()) {
|
if (categories.isEmpty()) {
|
||||||
item {
|
item {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue