Unable use a TextField at the bottom of the screen in a LazyColumn
Asked Answered
B

3

12

I have this code

setContent {
  val items = mutableListOf<Int>().apply {
    (1..100).forEach { add(it) }
  }
  LazyColumn {
    items(items) { item ->
      TextField("$item", {})
    }
  }
}

With android:windowSoftInputMode="adjustResize" in my AndroidManifest.xml.

If I click on a TextField at the top of the list, I can enter text fine.

If I click on a TextField near the bottom of the screen, the keyboard appears momentarily, then disappears quickly after, and prevents me from entering text.

How can I enter text when the TextField is at the bottom of the screen? Thanks!

Bilingual answered 21/8, 2022 at 23:27 Comment(5)
Interesting case... The keyboard DISAPPEARS after having appeared "momentarily". Adjust resize flag in the Manifest, only happens when the textfield in concern in at the bottom of the screen. Seems like a bug, really, but... Differential diagnosis, people - go.Proofread
Is there any modifier or properties added to TextField? It will be better you add proper code of TextFied with all properties you added.Polak
The diagnosis is done, Mistry. Diagnosed as a side-effect of Destructive Lazy Composition.Proofread
@Richard explained the reason in his answer, and it is a correct one. But newer Android versions (I tried it with Android 9 "Pie" (API level 28) behave differently – the soft keyboard pushes the visible content up, so you have no problem to enter text to the last TextField.Marella
Yes, I experienced that as well for another (minor) case. You don't even need adjustResize in your manifest for that to work. Apparently, that person and this one either forgot about their cases, or don't bother to stop wasting people's time by marking the questions as resolved.Proofread
P
11

Your keyboard disappears after having appeared for a brief, shiny moment. Here's the reason:

You tap the TextField, it calls it's built-in focus requestor, and requests the focus from the OS by calling appropriate (or inappropriate, who's to say) internal methods, as a result of which, the keyboard pops out (again, built-in mechanism.) and you can type all the more you want... AS LONG AS THE FIELD IS VISIBLE; or in Compose terms, long as the Composable holding the requestor, is in composition.

It should be clear, that once the Composable that owns the focus requestor goes off the screen, it is destroyed (well not every time, there are only certain specific cases when it is destroyed..., but yours is one of them), and when the Composable is destroyed, the focus requestor is destroyed. No focus requestor, no focus owner - the keyboard vanishes.

Now this is really important because you are using a LazyColumn, a lazy Composable, infamous for its merciless slaughtering of the Composables that are no longer visible to the user. HENCE, as long as it is the top (or other "visible") textfield that is in concern, it stays and works as expected. However, the bottom textfield, as the keyboard pops up, goes so much out of the visible bounds, that it gets slaughtered (recycled is the technical term, but what fun is that?), taking away the purpose of the keyboard.

Now, the lazy column, like any criminal, left a clue behind, and didn't notice it, which lead us to catch him red-handed. It is quite interesting, really, to see the column in action.

Now, workarounds include using a column, instead of a lazy column; creating your own lazy column using a custom lazy Composable, and manually handling the heap size for the Composable so the final field doesn't go out of composition.

That's it, you're cured.

Proofread answered 22/8, 2022 at 4:54 Comment(4)
Thats a very detailed and accurate answer. respect.Dismount
@Dismount I found a better metaphor. The lazy column is like a cannibalistic resource-less mother. She feeds her children to her other children who are currently hungry, just like in the case of a LazyColumn, when new items want resources, the old items who were previously fed well, vanish. They might actually have been "fed" to the new hungry babies. What is the Android Team up to!?Proofread
@RichardOnslowRoper do you have an example of the implementation of the workaround for this issue, thanks in advanceLobectomy
The manual column thing isn't yet possible afaik using high level APIs. The column bit is obvious, just swap the LazyColumn with a Column and it should work. I'll try to give a brief tutorial on that. So place your cursor between the word LazyColumn such that it lands directly between the 'y' and the 'C'. Till here, half the job is done. Give yourself a pat on the back. Take a break maybe, go for a jog or something. Then comes the fun part. You get to stroke a key repeatedly like a mad man. Press the Backspace key four times in a row and your code will magically start to work.Proofread
P
2

Just leaving another answer, since OP didn't verify other purpose of him specifying adjustResize,if whether removing or changing it will be fine, but another solution aside from the mentioned comment about different API version is specifying adjustPan, which worked in my case, either

via AndroidManifest

android:windowSoftInputMode="adjustPan"

or programmatically

window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)

Same code base but with adjustPan

enter image description here

Paltry answered 13/12, 2022 at 5:52 Comment(0)
T
2

This issue is fixed in the current alpha version 1.4.0-alpha05

https://issuetracker.google.com/issues/179203700

Tarantella answered 26/1, 2023 at 5:19 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Acea

© 2022 - 2024 — McMap. All rights reserved.