There is a feature request for this feature, I suggest your star it and maybe comment on it since it hasn't been updated for a while.
Until then you can use this hack. I render an invisible text field with extra lines so that it occupies the right size, and then apply that size to the real text field. I also pass modifier
and textStyle
as keys for remember
for heightUpdateNeeded
so that if you change them, the height will be recalculated. If any other parameters you pass may change the size of the view, you should pass them to remember as well.
@Composable
fun MinLinesOutlinedTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: @Composable (() -> Unit)? = null,
placeholder: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
minLines: Int,
maxLines: Int = Int.MAX_VALUE,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small,
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
) {
val heightState = remember { mutableStateOf<Int?>(null) }
var heightUpdateNeeded by remember(modifier, textStyle) { mutableStateOf(true) }
val height = with(LocalDensity.current) {
heightState.value?.toDp()
} // to use if nullable unwrapping
Box(modifier.height(IntrinsicSize.Min).width(IntrinsicSize.Min)) {
if (heightUpdateNeeded) {
OutlinedTextField(
value = value + "\n".repeat(minLines),
onValueChange = onValueChange,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
label = label,
placeholder = placeholder,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
isError = isError,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
singleLine = singleLine,
maxLines = maxLines,
interactionSource = interactionSource,
shape = shape,
colors = colors,
modifier = Modifier
.fillMaxSize()
.alpha(0f)
.onSizeChanged {
heightUpdateNeeded = false
println("onSizeChanged $it")
heightState.value = it.height
}
)
}
if (height != null) {
OutlinedTextField(
value = value,
onValueChange = onValueChange,
enabled = enabled,
readOnly = readOnly,
textStyle = textStyle,
label = label,
placeholder = placeholder,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
isError = isError,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
singleLine = singleLine,
maxLines = maxLines,
interactionSource = interactionSource,
shape = shape,
colors = colors,
modifier = Modifier
.fillMaxWidth()
.height(height)
)
}
}
}