Reputation: 31
I am working on a jetpack compose notes app. I used two textfield inside a column but the cursor keeps going behind the keyboard. I also checked official android architecture example apps. They also used some hack to keep the cursor in view.
Is there any solution.
Video: https://imgur.com/a/LCLwe7p Github: https://github.com/laraib07/zenote/blob/main/app/src/main/java/com/laraib07/zenote/ui/screen/add_edit/AddEditNote.kt
The cursor must remain on screen.
Upvotes: 2
Views: 515
Reputation: 41
you can try these steps:
android:windowSoftInputMode=adjustResize
on the activity in your manifest file. For example:<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
BringIntoViewRequester()
to scroll the container to the position where the cursor is presenting. Here is an example:val bringIntoViewRequester = remember { BringIntoViewRequester() }
val coroutineScope = rememberCoroutineScope()
var textFieldValue by remember { mutableStateOf(TextFieldValue()) }
BasicTextField(
value = textFieldValue,
onValueChange = { textFieldValue = it },
textStyle = TextStyle(fontSize = 30.sp),
onTextLayout = {
val cursorRect = it.getCursorRect(textFieldValue.selection.start)
coroutineScope.launch {
bringIntoViewRequester.bringIntoView(cursorRect)
}
},
modifier = Modifier
.bringIntoViewRequester(bringIntoViewRequester)
.fillMaxWidth()
)
Here's an example with two text fields inside a vertically scrollable column:
val bringIntoViewRequester1 = remember { BringIntoViewRequester() } // Text Field 1 BringIntoViewRequester()
val bringIntoViewRequester2 = remember { BringIntoViewRequester() } // Text Field 2 BringIntoViewRequester()
val coroutineScope = rememberCoroutineScope()
var textFieldValue1 by remember { mutableStateOf(TextFieldValue()) } // Text Field 1 value
var textFieldValue2 by remember { mutableStateOf(TextFieldValue()) } // Text Field 2 value
Column(
modifier = Modifier
.fillMaxSize()
.padding(10.dp)
.border(1.dp, Color.Red, RectangleShape)
.verticalScroll(rememberScrollState())
) {
Surface(modifier = Modifier.border(1.dp, Color.Black, RectangleShape)) {
BasicTextField(
value = textFieldValue1,
onValueChange = { textFieldValue1 = it },
textStyle = TextStyle(fontSize = 30.sp),
onTextLayout = {
var cursorRect = it.getCursorRect(textFieldValue1.selection.start) // Get Text Field 1 cursor position
coroutineScope.launch {
bringIntoViewRequester1.bringIntoView(cursorRect) // Scroll to Text Field 1 cursor position
}
},
modifier = Modifier
.bringIntoViewRequester(bringIntoViewRequester1) // Add BringIntoViewRequester() modifier for Text Field 1
.fillMaxWidth()
)
}
Surface(modifier = Modifier.border(1.dp, Color.Black, RectangleShape)) {
BasicTextField(
value = textFieldValue2,
onValueChange = { textFieldValue2 = it },
textStyle = TextStyle(fontSize = 30.sp),
onTextLayout = {
var cursorRect = it.getCursorRect(textFieldValue2.selection.start) // Get Text Field 2 cursor position
coroutineScope.launch {
bringIntoViewRequester2.bringIntoView(cursorRect) // Scroll to Text Field 2 cursor position
}
},
modifier = Modifier
.bringIntoViewRequester(bringIntoViewRequester2) // Add BringIntoViewRequester() modifier for Text Field 2
.fillMaxWidth()
)
}
}
Upvotes: 1