1

I'm developing a typical chat screen, with the text input at the bottom. The app has a bottom bar with tabs and a topbar.

I'm struggling at getting what I understand to be the expected behavior (Android, iOS):

  1. When keyboard is opened, text input is (directly) on top of keyboard.
  2. The topbar doesn't move, i.e. stays at top of screen.
  3. Bottom bar is visible at bottom of screen when keyboard is closed.

I've tried different combinations of using scaffold's innerPadding, applying imePadding() to different elements, or not applying it, etc. There's always a different issue that doesn't fulfill the 3 points above. E.g. topbar is pushed out of screen, there's space with size of tabbar between input and keyboard. Sometimes there are platform specific differences.

Are my expectations correct? if yes, what's wrong with the code? if not, what to change?

Here's a repo with this code: https://github.com/ivnsch/textfieldpadding/tree/6717e4d247970316bcc36d52427de408514cff83

enter image description here

Issue example when opening keyboard (current code):

enter image description here

Commenting imePadding(), space goes away, now topbar is pushed out:

enter image description here

package foo.bar.inputtestdemo

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.ui.tooling.preview.Preview

@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Preview
fun App() {
    Scaffold(
        topBar = {
            Column {
                TopAppBar(title = { Text("topbar") })
            }
        },
        bottomBar = { TabsBar() }
    ) { innerPadding ->

//      Box(modifier = Modifier.fillMaxSize()) {
        Box(modifier = Modifier.padding(innerPadding)) {
//      Box {
            Contents()
        }
    }
}

@Composable
private fun Contents() {
    val focusManager = LocalFocusManager.current

    Box {
        Column(
            modifier = Modifier
                .imePadding()
                .fillMaxSize()
                .pointerInput(Unit) {
                    detectTapGestures(onTap = {
                        focusManager.clearFocus()
                    })
                },
        ) {
            Box(
                modifier = Modifier
                    .weight(1f)
                    .fillMaxWidth(),
                contentAlignment = Alignment.Center
            ) {
                Text("Main content area")
            }

            BasicText()
        }
    }
}

@Composable
private fun BasicText() {
    var textState by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue("..."))
    }

    BasicTextField(
        value = textState,
        onValueChange = { textState = it },
        modifier = Modifier
            .height(60.dp)
            .fillMaxWidth()
            .background(Color.Yellow),
    )
}

@Composable
fun TabsBar() {
    NavigationBar(
        modifier = Modifier.height(100.dp),
        containerColor = Color.Green,
    ) { }
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.