I have code like this and I want the button on the bottom to be visible when keyboard is opened to edit the textfield.
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp)
                    .verticalScroll(rememberScrollState())
                    .imePadding(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(text = "LARGE TITLE", fontSize = 32.sp, fontWeight = FontWeight.Bold)
                Spacer(modifier = Modifier.height(400.dp))
                OutlinedTextField(value = "Sample Text", onValueChange = {})
                Spacer(modifier = Modifier.weight(1f))
                Button(onClick = { /*TODO*/ }) {
                    Text(text = "Sample Button")
                }
            }
        }
    }
I also have put  android:windowSoftInputMode="adjustResize" in manifest. I achieved my purpose by adding reverseScrolling = true (.verticalScroll(rememberScrollState(), reverseScrolling = true)) to the column modifier with help of an answer of @Halifax to this. I'm wondering how this has solved the issue exactly. Can I use this approach in similar views? I'm worried that it might cause some weird behavior if the screen got more complicated.


Here is a slightly different solution that keeps the button in the column. It uses the BringIntoViewRequester to scroll the button into view whenever the size of the column is changed.
    setContent {
        val bringIntoViewRequester = remember { BringIntoViewRequester() }
        val coroutineScope = rememberCoroutineScope()
        val bringButtonIntoView: () -> Unit = {
            coroutineScope.launch {
                delay(1)
                bringIntoViewRequester.bringIntoView()
            }
        }
        Box(modifier = Modifier.imePadding()) {
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp)
                    .verticalScroll(rememberScrollState())
                    .onSizeChanged { bringButtonIntoView() },
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(text = "LARGE TITLE", fontSize = 32.sp, fontWeight = FontWeight.Bold)
                Spacer(modifier = Modifier.height(400.dp))
                OutlinedTextField(value = "Sample Text", onValueChange = {})
                Spacer(modifier = Modifier.weight(1f))
                Button(
                    onClick = { /*TODO*/ },
                    modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester),
                ) {
                    Text(text = "Sample Button")
                }
            }
        }
    }
                        The reverseScrolling = true attribute reverses the scroll direction, similar to chat screens in messaging apps. This means the content starts from the bottom instead of the top. Consequently, the Button at the bottom is displayed above the keyboard.
However, if your content is large enough to be scrollable, such as when you have multiple OutlinedTextField elements, you may encounter the following issues:
Button will not remain visible above the keyboard.This setup only works when the content fits within the window and is not scrollable. If your content isn't scrollable, you can simply remove the scroll from the Column, and your problem will be resolved.
If your content is large and your Column is scrollable, you can solve this problem by placing the scrollable content in a Column with the weight(1f) modifier. Then, wrap it in a non-scrollable Column with the fillMaxSize() modifier, along with a Button that remains visible when the keyboard opens at the bottom.
First, ensure that the activity's windowSoftInputMode is set to adjustResize:
<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="adjustResize">
</activity>
Next, structure your content as follows:
Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(16.dp),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .weight(1f)
            .verticalScroll(rememberScrollState()),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "LARGE TITLE", fontSize = 32.sp, fontWeight = FontWeight.Bold)
        Spacer(modifier = Modifier.height(400.dp))
        OutlinedTextField(value = "Sample Text", onValueChange = {})
        Spacer(modifier = Modifier.height(400.dp))
        OutlinedTextField(value = "Sample Text", onValueChange = {})
        Spacer(modifier = Modifier.height(400.dp))
        OutlinedTextField(value = "Sample Text", onValueChange = {})
        Spacer(modifier = Modifier.height(400.dp))
    }
    Button(onClick = { /*TODO*/ }) {
        Text(text = "Sample Button")
    }
}
This approach ensures that your button remains visible above the keyboard while allowing the content to be scrollable.
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