lannyf
lannyf

Reputation: 11035

android, when typing in the text field, how to bring the last line into the text field when the content is over the maxheight limit

Having a "OutlinedTextField" with multiple lines in the "TextEditField" composable, and it has .heightIn(min = 56.dp, max = 160.dp) for maxHeight specified.

With this textfield if newly typed in text makes the content grow over the max height it will not be seen in the text field, instead it is hidden at the bottom of the textfield outside its view, and only after manually scroll the text will be brought up and visually displayed in the text field.

When typing new text how to auto scroll to the bottom of the textfield if the content has reached max height limit?

@Composable
fun UserScreen(...){

    val scrollState = rememberScrollState()
    val coroutineScope = rememberCoroutineScope()
    val bringIntoViewRequester = remember { BringIntoViewRequester() }

    Surface(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
                .imePadding()
                .verticalScroll(scrollState)  // Make the entire screen scrollable
        ) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(28.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
 ...
            TextEditField(
                bringIntoViewRequester = bringIntoViewRequester,
                coroutineScope = coroutineScope,
                labelValue = "",
                painterResource = null,
                singleLine = false,
                onTextChanged = {  },
                isErrorState = false,
                value = "",
                editable = true,
                modifier = Modifier
                    .fillMaxWidth()
                    .heightIn(min = 56.dp, max = 160.dp)  // Set a max height for the text field
                    .verticalScroll(rememberScrollState())  // Make it scrollable
            )
            ...
        }
     }
}

@Composable
fun TextEditField(
    bringIntoViewRequester: BringIntoViewRequester,
    coroutineScope: CoroutineScope,
    labelValue: String,
    painterResource: Painter? = null,
    singleLine: Boolean = true,
    onTextChanged: (String) -> Unit,
    isErrorState: Boolean = false,
    value: String,
    editable: Boolean = true,
    infoMessage: String? = null,
    modifier: Modifier = Modifier
        .fillMaxWidth()
        .clip(componentShapes.small),
) {
    val textValue = remember {
        mutableStateOf(value)
    }
    debounceInput(textValue) { debouncedValue ->
        onTextChanged(debouncedValue)
    }

    OutlinedTextField(
        modifier = modifier
            .bringIntoViewRequester(bringIntoViewRequester)
            .onFocusChanged { focusState ->
                if (focusState.isFocused) {
                    coroutineScope.launch {
                        bringIntoViewRequester.bringIntoView()
                    }
                }
            },
        label = { Text(text = labelValue) },

        keyboardOptions = KeyboardOptions.Default.copy(
            keyboardType = KeyboardType.Password,
            imeAction = if (singleLine) ImeAction.Next else ImeAction.Default
        ),

        singleLine = singleLine,
        value = textValue.value,
        enabled = editable,
        readOnly = !editable,
        onValueChange = {
            textValue.value = it
        },
        isError = isErrorState
    )
}

Upvotes: 1

Views: 49

Answers (2)

BenjyTec
BenjyTec

Reputation: 10887

Please have a look at the maxLines parameter of OutlinedTextField:

maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE    

the maximum height in terms of maximum number of visible lines. It is required that 1 <= minLines <= maxLines. This parameter is ignored when singleLine is true.

As long as the number of lines is <= maxLines, the OutlinedTextField will grow in height.
If the number of lines is > maxLines, it will automatically allow scrolling while at the same time always scrolling alongside the cursor.

OutlinedTextField(
    modifier = Modifier.fillMaxWidth(),
    value = textValue,
    onValueChange = {
        textValue = it
    },
    singleLine = false,
    maxLines = 4
)

Output:

Screen Recording

Upvotes: 0

Shreyash.K
Shreyash.K

Reputation: 1148

BasicTextField from version 1.7.0+ exposes its internal scroll state which you can use to scroll to a particular position.

Note that this Scroll State is different than the one attached to the Modifier.


    val scrollState = rememberScrollState()

    BasicTextField(
        scrollState = scrollState,
        value = value,
        onValueChange = { },
        modifier = Modifier,
    )

    LaunchedEffect(Unit) {
        /// Use this to scroll to the end
        scrollState.scrollTo(scrollState.maxValue)
    }

Old answer

I would suggest you to use BasicTextField2 going forward. It is a new API intended to fix many of the shortcomings of TextField(BasicTextField).

Looks like BasicTextField2 was merged to BasicTextField 🎉

Upvotes: 0

Related Questions