[英]Showing a text field in the app bar in Jetpack Compose with Material3
许多 Android 应用程序在应用程序栏/工具栏中都有一个搜索框,看起来有点像这个截图:
如何在 Jetpack Compose + Material3 中重新创建类似的东西? 我希望文本字段具有以下功能:
我试图通过将TextField
放在CenterAlignedTopAppBar
的title
中来重现 Jetpack Compose + Material3 中的相同行为,但结果看起来不太好。 文本字段使用了应用栏的整个高度,并具有灰色背景,这两个东西看起来都很奇怪。
经过一些工程,我想出了一个AppBarTextField
,请参见下面的代码。 我不得不使用较低级别的BasicTextField
,因为普通的TextField
不够可定制。 与主题和颜色有关的代码直接从TextField
的实现中复制,因此主题的自定义通常适用于文本字段的组件。
AppBarTextField
可组合接受的参数是:
value
: 要在文本字段中显示的内容字符串onValueChange
:在这里传递新值(记得更新value
!)hint
:当文本字段为空时显示的提示modifier
、 keyboardOptions
和keyboardActions
:它们直接传递给BasicTextField
并且它们的行为与普通TextField
中的行为相同。 如果您需要自定义其他TextField
参数,只需将它们添加到 function 签名中,然后将它们传递给BasicTextField
。实现了请求的功能:
SideEffect
实现的,因此它只会发生在第一个合成上TextFieldValue
所需的第一个组合的末尾.background()
修饰符存在(虽然它在普通TextField
中)decorationBox
参数中将placeholder
传递给TextFieldDecorationBox
来添加提示(请注意,这也可以使用TextField
)TextFieldDecorationBox
的填充现在也只有4dp
。 此处添加了填充(而不是在BasicTextField
上使用修饰符),因为否则底线指示器(而是使用.indicatorLine()
修饰符显示)将无法正确显示。@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppBarTextField(
value: String,
onValueChange: (String) -> Unit,
hint: String,
modifier: Modifier = Modifier,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
) {
val interactionSource = remember { MutableInteractionSource() }
val textStyle = LocalTextStyle.current
val colors = TextFieldDefaults.textFieldColors()
// If color is not provided via the text style, use content color as a default
val textColor = textStyle.color.takeOrElse {
MaterialTheme.colorScheme.onSurface
}
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor, lineHeight = 50.sp))
// request focus when this composable is first initialized
val focusRequester = FocusRequester()
SideEffect {
focusRequester.requestFocus()
}
// set the correct cursor position when this composable is first initialized
var textFieldValue by remember {
mutableStateOf(TextFieldValue(value, TextRange(value.length)))
}
textFieldValue = textFieldValue.copy(text = value) // make sure to keep the value updated
CompositionLocalProvider(
LocalTextSelectionColors provides LocalTextSelectionColors.current
) {
BasicTextField(
value = textFieldValue,
onValueChange = {
textFieldValue = it
// remove newlines to avoid strange layout issues, and also because singleLine=true
onValueChange(it.text.replace("\n", ""))
},
modifier = modifier
.fillMaxWidth()
.heightIn(32.dp)
.indicatorLine(
enabled = true,
isError = false,
interactionSource = interactionSource,
colors = colors
)
.focusRequester(focusRequester),
textStyle = mergedTextStyle,
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
interactionSource = interactionSource,
singleLine = true,
decorationBox = { innerTextField ->
// places text field with placeholder and appropriate bottom padding
TextFieldDefaults.TextFieldDecorationBox(
value = value,
visualTransformation = VisualTransformation.None,
innerTextField = innerTextField,
placeholder = { Text(text = hint) },
singleLine = true,
enabled = true,
isError = false,
interactionSource = interactionSource,
colors = colors,
contentPadding = PaddingValues(bottom = 4.dp)
)
}
)
}
}
这是一个示例用法:
var value by rememberSaveable { mutableStateOf("initial content") }
CenterAlignedTopAppBar(
title = {
AppBarTextField(
value = value,
onValueChange = { newValue -> value = newValue },
hint = "A hint..."
)
},
navigationIcon = /* the back icon */,
actions = /* the search icon */
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.