Android Compose TextField: как установить ровно 3 строки

Я хочу создать ровно 3 строки:

Я хочу видеть 3 строки даже без текста в этом TextField, т.е. мне нужен прямой эквивалент EditText.lines в классическом формате xml.

Мой неработающий код:

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

Не могли бы вы помочь мне?

4 ответа

Мы можем отобразить многострочный текст редактирования, установив высоту OutlinedTextField. Тестируется следующий пример.

                      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
                )

Прикрепленное изображение ниже.

введите описание изображения здесь

Начиная с Начиная с M21.4.0-alpha02и М31.1.0-alpha02вы можете использовать minLinesатрибут вTextFieldиOutlinedTextField:

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

Его можно использовать с M2 и M3.

Для этой функции на добавление есть запросфункции , я предлагаю вам пометить ее и, возможно, прокомментировать ее, поскольку она не обновлялась какое-то время.

А пока вы можете использовать эту хитрость. Я визуализирую невидимое текстовое поле с дополнительными строками, чтобы оно занимало нужный размер, а затем применяю этот размер к реальному текстовому полю. Я также прохожу modifier а также textStyle как ключи для remember для heightUpdateNeededтак что если вы их измените, высота будет пересчитана. Если какие-либо другие параметры, которые вы передаете, могут изменить размер представления, вы также должны передать их, чтобы запомнить.

      @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)
            )
        }
    }
}

У меня была та же проблема, и я нашел решение на данный момент, в основном, Google уже решил проблему, но она находится в версии Alpha (androidx.compose.foundation:foundation:1.4.0-alpha01).

И чтобы решить эту проблему, я просто копирую и вставляю HeightInLinesModifier.kt в наш проект, и он отлично работает с помощью Modifier.heightInLines . И как только он станет доступен в стабильной версии, нам просто нужно удалить этот файл из нашего проекта и изменить импорт, и все готово.

Другие вопросы по тегам