I want to create TextField with exact 3 lines:

destination

I want to see 3 lines even without any text in this TextField, i.e. I need a direct equivalent of EditText.lines in classic xml layout.

My not working code is:

OutlinedTextField(value = currentText,onValueChange = { currentText = it },label = { Text ("Label") },maxLines = 3,modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(16.dp),singleLine = false)

Could you help me?

4

Best Answer


We can show multiline edittext by setting height of OutlinedTextField. Following example is tested.

 OutlinedTextField(modifier = Modifier.fillMaxWidth().height(120.dp).padding(start = 15.dp, top = 10.dp, end = 15.dp).background(Color.White, RoundedCornerShape(5.dp)),shape = RoundedCornerShape(5.dp),value = text,onValueChange = { text = it },keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),maxLines = 3,textStyle = MaterialTheme.typography.caption)

Attached image below.

enter image description here

Starting from Starting from M2 1.4.0-alpha02 and M3 1.1.0-alpha02 you can use the minLines attribute in the TextField and OutlinedTextField:

OutlinedTextField(value = text,onValueChange = { text = it },label = { Text ("Label") },minLines = 3,maxLines = 3,modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(16.dp))

enter image description hereenter image description here

It can be used with M2 and M3.

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.

@Composablefun 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 unwrappingBox(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 = falseprintln("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))}}}

I had the same problem, and I found the solution as of now, basically, google has already solved the issue but it is in the Alpha release (androidx.compose.foundation:foundation:1.4.0-alpha01).

And to solve the issue I just copy paste HeightInLinesModifier.kt to our project and it is working fine by using Modifier.heightInLines. And as soon as it will become available in stable release We just need to delete this File from our project and change the import and we are good to go