Refactor text fields for number input

- removed custom keyboard to improve accessibility
This commit is contained in:
Sad Ellie 2024-01-17 18:12:55 +03:00
parent 84c29682f8
commit 5141652394
7 changed files with 102 additions and 320 deletions

View File

@ -0,0 +1,65 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2024 Elshan Agaev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.core.ui.common.textfield
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
@Composable
fun OutlinedDecimalTextField(
modifier: Modifier,
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
label: @Composable () -> Unit,
expressionFormatter: VisualTransformation,
imeAction: ImeAction = ImeAction.Next
) {
OutlinedTextField(
modifier = modifier,
value = value,
onValueChange = onValueChange,
trailingIcon = {
AnimatedVisibility(value.text.isNotBlank(), enter = scaleIn(), exit = scaleOut()) {
IconButton(onClick = { onValueChange(TextFieldValue()) }) {
Icon(Icons.Outlined.Clear, null)
}
}
},
label = label,
singleLine = true,
visualTransformation = expressionFormatter,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Decimal,
imeAction = imeAction
),
)
}

View File

@ -153,7 +153,6 @@ private fun BodyMassScreen(
onValueChange = updateHeight1,
label = "${stringResource(R.string.body_mass_height)}, ${stringResource(R.string.unit_centimeter_short)}",
expressionFormatter = expressionTransformer,
imeAction = ImeAction.Next
)
} else {
Row(
@ -165,7 +164,6 @@ private fun BodyMassScreen(
onValueChange = updateHeight1,
label = "${stringResource(R.string.body_mass_height)}, ${stringResource(R.string.unit_foot_short)}",
expressionFormatter = expressionTransformer,
imeAction = ImeAction.Next
)
BodyMassTextField(
modifier = Modifier.weight(1f),
@ -173,7 +171,6 @@ private fun BodyMassScreen(
onValueChange = updateHeight2,
label = "${stringResource(R.string.body_mass_height)}, ${stringResource(R.string.unit_inch_short)}",
expressionFormatter = expressionTransformer,
imeAction = ImeAction.Next
)
}
}

View File

@ -19,32 +19,25 @@
package com.sadellie.unitto.feature.bodymass.components
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.common.textfield.OutlinedDecimalTextField
@Composable
internal fun BodyMassTextField(
modifier: Modifier,
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
label: String,
onValueChange: (TextFieldValue) -> Unit,
expressionFormatter: VisualTransformation,
imeAction: ImeAction
imeAction: ImeAction = ImeAction.Next
) {
val focusManager = LocalFocusManager.current
OutlinedTextField(
OutlinedDecimalTextField(
modifier = modifier,
value = value,
onValueChange = {
@ -56,13 +49,7 @@ internal fun BodyMassTextField(
onValueChange(it.copy(cleanText))
},
label = { AnimatedContent(label) { Text(it) } },
singleLine = true,
visualTransformation = expressionFormatter,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Decimal,
expressionFormatter = expressionFormatter,
imeAction = imeAction
),
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() })
)
}

View File

@ -26,11 +26,9 @@ import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
@ -63,7 +61,6 @@ internal fun DateCalculatorScreen(
val addSubtractLabel = "${stringResource(R.string.date_calculator_add)}/${stringResource(R.string.date_calculator_subtract)}"
val differenceLabel = stringResource(R.string.date_calculator_difference)
val focusManager = LocalFocusManager.current
var showKeyboard by remember { mutableStateOf(false) }
val allTabs = remember { listOf(addSubtractLabel, differenceLabel) }
val pagerState = rememberPagerState { allTabs.size }
@ -99,14 +96,9 @@ internal fun DateCalculatorScreen(
verticalAlignment = Alignment.Top
) { page ->
when (page) {
0 -> AddSubtractPage(
showKeyboard = showKeyboard,
toggleKeyboard = {showKeyboard = it }
)
0 -> AddSubtractPage()
1 -> {
focusManager.clearFocus(true)
showKeyboard = false
SideEffect { focusManager.clearFocus(true) }
DateDifferencePage()
}
}

View File

@ -23,14 +23,10 @@ import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.provider.CalendarContract
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
@ -50,25 +46,20 @@ import androidx.compose.material.icons.filled.Event
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.Remove
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import com.sadellie.unitto.core.ui.WindowHeightSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
@ -77,12 +68,9 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.sadellie.unitto.core.base.R
import com.sadellie.unitto.core.ui.LocalWindowSize
import com.sadellie.unitto.core.ui.common.textfield.addTokens
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer
import com.sadellie.unitto.core.ui.showToast
import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils
import com.sadellie.unitto.feature.datecalculator.components.AddSubtractKeyboard
import com.sadellie.unitto.feature.datecalculator.components.DateTimeDialogs
import com.sadellie.unitto.feature.datecalculator.components.DateTimeSelectorBlock
import com.sadellie.unitto.feature.datecalculator.components.DialogState
@ -92,15 +80,11 @@ import java.time.ZonedDateTime
@Composable
internal fun AddSubtractPage(
viewModel: AddSubtractViewModel = hiltViewModel(),
showKeyboard: Boolean,
toggleKeyboard: (Boolean) -> Unit,
) {
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
AddSubtractView(
uiState = uiState,
showKeyboard = showKeyboard,
toggleKeyboard = toggleKeyboard,
updateStart = viewModel::updateStart,
updateYears = viewModel::updateYears,
updateMonths = viewModel::updateMonths,
@ -115,8 +99,6 @@ internal fun AddSubtractPage(
@Composable
private fun AddSubtractView(
uiState: AddSubtractState,
showKeyboard: Boolean,
toggleKeyboard: (Boolean) -> Unit,
updateStart: (ZonedDateTime) -> Unit,
updateYears: (TextFieldValue) -> Unit,
updateMonths: (TextFieldValue) -> Unit,
@ -126,20 +108,9 @@ private fun AddSubtractView(
updateAddition: (Boolean) -> Unit,
) {
val mContext = LocalContext.current
val focusManager = LocalFocusManager.current
var dialogState by remember { mutableStateOf(DialogState.NONE) }
var addSymbol: ((TextFieldValue) -> Unit)? by remember { mutableStateOf(null) }
var focusedTextFieldValue: TextFieldValue? by remember { mutableStateOf(null) }
LaunchedEffect(addSymbol, focusedTextFieldValue) {
toggleKeyboard((addSymbol != null) and (focusedTextFieldValue != null))
}
BackHandler(showKeyboard) {
focusManager.clearFocus()
addSymbol = null
focusedTextFieldValue = null
val expressionTransformer = remember(uiState.formatterSymbols) {
ExpressionTransformer(uiState.formatterSymbols)
}
val showResult = remember(uiState.start, uiState.result) { uiState.start != uiState.result }
@ -241,127 +212,58 @@ private fun AddSubtractView(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
TimeUnitTextField(
modifier = Modifier
.onFocusEvent {
if (it.hasFocus) {
addSymbol = updateYears
focusedTextFieldValue = uiState.years
}
}
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
value = uiState.years,
onValueChange = updateYears,
label = stringResource(R.string.date_calculator_years),
formatterSymbols = uiState.formatterSymbols
expressionFormatter = expressionTransformer,
)
Row(
modifier = Modifier
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
TimeUnitTextField(
modifier = Modifier
.onFocusEvent {
if (it.hasFocus) {
addSymbol = updateMonths
focusedTextFieldValue = uiState.months
}
}
.weight(1f),
modifier = Modifier.weight(1f),
value = uiState.months,
onValueChange = updateMonths,
label = stringResource(R.string.date_calculator_months),
formatterSymbols = uiState.formatterSymbols
expressionFormatter = expressionTransformer,
)
TimeUnitTextField(
modifier = Modifier
.onFocusEvent {
if (it.hasFocus) {
addSymbol = updateDays
focusedTextFieldValue = uiState.days
}
}
.weight(1f),
modifier = Modifier.weight(1f),
value = uiState.days,
onValueChange = updateDays,
label = stringResource(R.string.date_calculator_days),
formatterSymbols = uiState.formatterSymbols
expressionFormatter = expressionTransformer,
)
}
Row(
modifier = Modifier
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
TimeUnitTextField(
modifier = Modifier
.onFocusEvent {
if (it.hasFocus) {
addSymbol = updateHours
focusedTextFieldValue = uiState.hours
}
}
.weight(1f),
modifier = Modifier.weight(1f),
value = uiState.hours,
onValueChange = updateHours,
label = stringResource(R.string.date_calculator_hours),
formatterSymbols = uiState.formatterSymbols
expressionFormatter = expressionTransformer,
)
TimeUnitTextField(
modifier = Modifier
.onFocusEvent {
if (it.hasFocus) {
addSymbol = updateMinutes
focusedTextFieldValue = uiState.minutes
}
}
.weight(1f),
modifier = Modifier.weight(1f),
value = uiState.minutes,
onValueChange = updateMinutes,
label = stringResource(R.string.date_calculator_minutes),
formatterSymbols = uiState.formatterSymbols
expressionFormatter = expressionTransformer,
imeAction = ImeAction.Done
)
}
}
}
}
AnimatedVisibility(
visible = showKeyboard,
enter = slideInVertically { it / 2 } + fadeIn(),
exit = slideOutVertically { it / 2 } + fadeOut()
) {
HorizontalDivider()
AddSubtractKeyboard(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.fillMaxHeight(if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) 0.4f else 0.6f)
.padding(2.dp, 4.dp),
addSymbol = {
val newValue = focusedTextFieldValue?.addTokens(it)
if (newValue != null) {
addSymbol?.invoke(newValue)
}
},
deleteSymbol = {
val newValue = focusedTextFieldValue?.deleteTokens()
if (newValue != null) {
addSymbol?.invoke(newValue)
}
},
onConfirm = {
focusManager.clearFocus()
addSymbol = null
focusedTextFieldValue = null
},
allowVibration = uiState.allowVibration,
imeAction = if (addSymbol == updateMinutes) ImeAction.Done else ImeAction.Next
)
}
}
DateTimeDialogs(
@ -399,8 +301,6 @@ fun AddSubtractViewPreview() {
start = ZonedDateTimeUtils.nowWithMinutes(),
result = ZonedDateTimeUtils.nowWithMinutes().plusSeconds(1)
),
showKeyboard = false,
toggleKeyboard = {},
updateStart = {},
updateYears = {},
updateMonths = {},

View File

@ -1,141 +0,0 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2023 Elshan Agaev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.feature.datecalculator.components
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import com.sadellie.unitto.core.base.Token
import com.sadellie.unitto.core.ui.LocalWindowSize
import com.sadellie.unitto.core.ui.WindowHeightSizeClass
import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall
import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled
import com.sadellie.unitto.core.ui.common.KeyboardButtonLight
import com.sadellie.unitto.core.ui.common.KeypadFlow
import com.sadellie.unitto.core.ui.common.icons.IconPack
import com.sadellie.unitto.core.ui.common.icons.iconpack.Backspace
import com.sadellie.unitto.core.ui.common.icons.iconpack.Check
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key0
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key1
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key2
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key3
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key4
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key5
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key6
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key7
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key8
import com.sadellie.unitto.core.ui.common.icons.iconpack.Key9
import com.sadellie.unitto.core.ui.common.icons.iconpack.Tab
@Composable
internal fun AddSubtractKeyboard(
modifier: Modifier,
addSymbol: (String) -> Unit,
deleteSymbol: () -> Unit,
onConfirm: () -> Unit,
allowVibration: Boolean,
imeAction: ImeAction,
focusManager: FocusManager = LocalFocusManager.current
) {
Row(
modifier = modifier
) {
KeypadFlow(
modifier = Modifier
.fillMaxHeight()
.weight(3f),
rows = 4,
columns = 3
) { width, height ->
val buttonModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
KeyboardButtonLight(buttonModifier, IconPack.Key7, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._7) }
KeyboardButtonLight(buttonModifier, IconPack.Key8, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._8) }
KeyboardButtonLight(buttonModifier, IconPack.Key9, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._9) }
KeyboardButtonLight(buttonModifier, IconPack.Key4, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._4) }
KeyboardButtonLight(buttonModifier, IconPack.Key5, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._5) }
KeyboardButtonLight(buttonModifier, IconPack.Key6, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._6) }
KeyboardButtonLight(buttonModifier, IconPack.Key1, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._1) }
KeyboardButtonLight(buttonModifier, IconPack.Key2, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._2) }
KeyboardButtonLight(buttonModifier, IconPack.Key3, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._3) }
Spacer(buttonModifier)
KeyboardButtonLight(buttonModifier, IconPack.Key0, allowVibration, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) }
Spacer(buttonModifier)
}
KeypadFlow(
modifier = Modifier
.fillMaxHeight()
.weight(1f),
rows = 2,
columns = 1,
// In digits keypad there are 4 rows with verticalPadding set to 10
// In this keypad we have 2 times less rows, we use 2 times smaller verticalPadding -> 5
verticalPadding = 5
) { width, height ->
val mainButtonModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
val actionIconHeight = if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) 0.8f else 1.3f
Crossfade(
targetState = imeAction == ImeAction.Next,
modifier = mainButtonModifier,
label = "Primary button animation"
) { showNext ->
if (showNext) {
KeyboardButtonFilled(Modifier.fillMaxSize(), IconPack.Tab, allowVibration, actionIconHeight) { focusManager.moveFocus(FocusDirection.Next) }
} else {
KeyboardButtonFilled(Modifier.fillMaxSize(), IconPack.Check, allowVibration, actionIconHeight) { onConfirm() }
}
}
KeyboardButtonLight(mainButtonModifier, IconPack.Backspace, allowVibration, actionIconHeight) { deleteSymbol() }
}
}
}
@Preview
@Composable
fun PreviewAddSubtractKeyboardNew() {
AddSubtractKeyboard(
modifier = Modifier
.fillMaxSize(),
addSymbol = {},
deleteSymbol = {},
onConfirm = {},
allowVibration = true,
imeAction = ImeAction.Next
)
}

View File

@ -18,50 +18,32 @@
package com.sadellie.unitto.feature.datecalculator.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.animation.AnimatedContent
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
import androidx.compose.ui.text.input.VisualTransformation
import com.sadellie.unitto.core.ui.common.textfield.OutlinedDecimalTextField
@Composable
internal fun TimeUnitTextField(
modifier: Modifier,
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
label: String,
formatterSymbols: FormatterSymbols
) = CompositionLocalProvider(LocalTextInputService provides null) {
OutlinedTextField(
onValueChange: (TextFieldValue) -> Unit,
expressionFormatter: VisualTransformation,
imeAction: ImeAction = ImeAction.Next,
) {
OutlinedDecimalTextField(
modifier = modifier,
value = value,
onValueChange = { newValue ->
onValueChange(newValue.copy(newValue.text.filter { it.isDigit() }))
},
label = { Text(label, color = MaterialTheme.colorScheme.onSurfaceVariant) },
trailingIcon = {
AnimatedVisibility(
visible = value.text.isNotBlank(),
enter = scaleIn(),
exit = scaleOut()
) {
IconButton(onClick = { onValueChange(TextFieldValue()) }) {
Icon(Icons.Outlined.Clear, null)
}
}
},
visualTransformation = ExpressionTransformer(formatterSymbols)
label = { AnimatedContent(label) { Text(it) } },
expressionFormatter = expressionFormatter,
imeAction = imeAction
)
}