Reputation: 11035
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
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 whensingleLine
istrue
.
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:
Upvotes: 0
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)
}
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