In Android View System, when cursor(cursor of EditText view in ScrollView) is out of visible area, Android automatically scroll screen to down to make cursor always visible.

Is there way to achieve this in android Jetpack Compose?
BasicTextField in LazyColumn seems to not support this behavior basically.

+)
Here is a composable codes sample that can regenerate this issue.
@Composable
fun TestScreen() {
val scaffoldState = rememberScaffoldState()
var content by remember { mutableStateOf("") }
Scaffold(
scaffoldState = scaffoldState,
floatingActionButtonPosition = FabPosition.Center,
) {
val lazyListState = rememberLazyListState()
LazyColumn(
state = lazyListState,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
item {
BasicTextField(
value = content,
onValueChange = { content = it },
modifier = Modifier
.background(color = Color.Green)
.fillMaxWidth()
.wrapContentHeight()
)
}
}
}
}
Activity Declaration in AndroidManifest.xml file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.test">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Test">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Test"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
you can create an extension to calculate what line the cursor are by TextFieldValue as above:
val TextFieldValue.selectionLine: Int
get() = text.take(selection.start).count { it == '\n' } + 1
and use as following:
val scrollState = rememberScrollState()
var textFieldValue by remember {
mutableStateOf(value = TextFieldValue())
}
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = { AppBar(onNavigationIconClick = navigateUp) },
) { padding ->
val textStyle = MaterialTheme.typography.bodyLarge.copy(
color = MaterialTheme.colorScheme.onBackground,
)
val lineHeight = with(LocalDensity.current) {
textStyle.lineHeight.value.dp.roundToPx()
}
LaunchedEffect(key1 = textFieldValue) {
scrollState.animateScrollTo(value = (textFieldValue.selectionLine - 1) * lineHeight)
}
BasicTextField(
modifier = Modifier
.fillMaxSize()
.verticalScroll(state = scrollState),
value = textFieldValue,
onValueChange = { textFieldValue = it },
textStyle = textStyle,
decorationBox = { innerTextField ->
Box(
modifier = Modifier.padding(paddingValues = padding),
) {
innerTextField()
}
}
)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With