7

I have a Compose activity, where there's a top app bar, and some TextFields towards the bottom of the screen. When I focus on one of the TextFields and the keyboard is invoked, I want the text field to appear above the keyboard, so I can see what I'm typing. This works fine, however the whole screen content is pushed upwards making the top app bar disappear or be cut off at the top.

I think ideally, the top app bar would be pinned to the top, and only the contents below would shift. It doesn't matter if the top app bar is part of the scaffold, or above the scaffold in a Column:

    Scaffold(
        topBar = {
            TopAppBar("...")
        }
    ) {
        // scrollable contents with TextFields
    }

---> OR

    Column {
        TopAppBar("...")
        Scaffold {
            // scrollable contents with TextFields
        }
    }

This is the unwanted behaviour illustrated:

enter image description here

Is there a way to achieve my desired behaviour of pinning the top app bar? Should the top app bar be pushed up by default in Compose?

Martyna Maron
  • 371
  • 4
  • 19

3 Answers3

2

It looks like you have to specify a weight to one of your composable.

Taking some reference from an answer from this post. Assuming you have set adjustResize in your manifest,

android:windowSoftInputMode="adjustResize"/>

you can consider this as a rough solution

Scaffold(
    topBar = {
        TopAppBar(title = { Text("Hello World")})
    }
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(it)
    ) {

        Box(
            modifier = Modifier
                .weight(1f)
                .background(Color.Gray)
                .fillMaxWidth()
        )

        Box(
            modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight()
                .background(Color(0xFF6f4d8c)),
            contentAlignment = Alignment.Center
        ) {
            TextField(
                value = "User Name",
                onValueChange = {}
            )
        }

        Box(
            modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight()
                .background(Color(0xFF6286bd)),
            contentAlignment = Alignment.Center
        ) {
            TextField(
                value = "Password",
                onValueChange = {}
            )
        }
    }
}

enter image description here

I just put some colors to show how the widgets occupy the space in their parent Column.

z.g.y
  • 5,512
  • 4
  • 10
  • 36
  • 1
    Thank you, I think `android:windowSoftInputMode="adjustResize` is what I was missing actually - as long as the text field is visible on the screen, but the resizing doesn't affect the top app bar, it's all good! – Martyna Maron Dec 12 '22 at 17:29
2

Summarize:
There are four options for the softInputMode which controls the soft keyboard or others:

  1. SOFT_INPUT_ADJUST_UNSPECIFIED
    (Determined by the systems)
  2. SOFT_INPUT_ADJUST_RESIZE / SOFT_INPUT_MODE_CHANGED
    (Calculate size and adapt)
  3. SOFT_INPUT_ADJUST_PAN
    (Move as a whole)
  4. SOFT_INPUT_ADJUST_NOTHING
    (Do nothing)

So the solution is setting adjustResize in your manifest

android:windowSoftInputMode="adjustResize"/>

but sometimes you must to write this at the override fun onCreate(savedInstanceState: Bundle?)

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

BUI IF YOU WANT TO USE Scaffold
The best way is write

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)

and add this to the content of Scaffold

Modifier.navigationBarsPadding()

add this to TextField

Modifier.imePadding()

It has been bothering me for a long time...

RYXCP
  • 21
  • 3
0

Try this

class YourActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) { 
        window.setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
        );
        setContent { /* Composable Content */ }
    }
}
Javlon
  • 1,108
  • 2
  • 15
  • 29