Status Update
Comments
an...@google.com <an...@google.com>
wa...@gmail.com <wa...@gmail.com> #2
This is a particularly hard device to come by - do you happen to have access to the device? If so could you provide us with the output of: adb shell dumpsys media.camera > info.txt
Thanks!
wa...@gmail.com <wa...@gmail.com> #3
Stacktrace:
Caused by: java.lang.IllegalArgumentException: Can not get supported output size under supported maximum for the format: 34
at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes(SupportedSurfaceCombination.java:355)
at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSuggestedResolutions(SupportedSurfaceCombination.java:197)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:198)
at androidx.camera.core.CameraX.calculateSuggestedResolutions(CameraX.java:943)
at androidx.camera.core.CameraX.bindToLifecycle(CameraX.java:293)
at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:227)
Below are some findings based on our debugging
When Dex is connected
previewConfig.getMaxResolution() is returning "731x411" as maxSize.
Inside Preview.Builder.build() -> Default_MAX_resolution is set to "CameraX.getSurfaceManager().getPreviewSize()" which is 731x411
this is being picked as maxSize.
While rendering maxSize is 731x411 and minSize is 640x480 and below are available outputSizes
0 = {Size@11860} "4032x3024"
1 = {Size@11861} "3984x2988"
2 = {Size@11862} "4032x2268"
3 = {Size@11863} "3024x3024"
4 = {Size@11864} "2976x2976"
5 = {Size@11865} "3840x2160"
6 = {Size@11866} "3264x2448"
7 = {Size@11867} "4032x1960"
8 = {Size@11868} "2880x2160"
9 = {Size@11869} "3264x1836"
10 = {Size@11870} "2160x2160"
11 = {Size@11871} "2560x1440"
12 = {Size@11872} "2224x1080"
13 = {Size@11873} "2048x1152"
14 = {Size@11874} "1920x1080"
15 = {Size@11875} "1440x1080"
16 = {Size@11876} "1088x1088"
17 = {Size@11877} "1280x720"
18 = {Size@11878} "1024x768"
19 = {Size@11879} "1056x704"
20 = {Size@11880} "960x720"
21 = {Size@11881} "960x540"
22 = {Size@11882} "720x720"
23 = {Size@11883} "800x450"
24 = {Size@11884} "720x480"
25 = {Size@11885} "640x480"
26 = {Size@11886} "352x288"
27 = {Size@11887} "320x240"
28 = {Size@11888} "256x144"
29 = {Size@11889} "176x144"
and couldn't find any size in this range.
When Dex not connected
minsize = 640x480
maxsize = 1920x1080
0 = {Size@11836} "4032x3024"
1 = {Size@11837} "3984x2988"
2 = {Size@11838} "4032x2268"
3 = {Size@11839} "3024x3024"
4 = {Size@11840} "2976x2976"
5 = {Size@11841} "3840x2160"
6 = {Size@11842} "3264x2448"
7 = {Size@11843} "4032x1960"
8 = {Size@11844} "2880x2160"
9 = {Size@11845} "3264x1836"
10 = {Size@11846} "2160x2160"
11 = {Size@11847} "2560x1440"
12 = {Size@11848} "2224x1080"
13 = {Size@11849} "2048x1152"
14 = {Size@11850} "1920x1080"
15 = {Size@11851} "1440x1080"
16 = {Size@11852} "1088x1088"
17 = {Size@11853} "1280x720"
18 = {Size@11854} "1024x768"
19 = {Size@11855} "1056x704"
20 = {Size@11856} "960x720"
21 = {Size@11857} "960x540"
22 = {Size@11858} "720x720"
23 = {Size@11859} "800x450"
24 = {Size@11860} "720x480"
25 = {Size@11861} "640x480"
26 = {Size@11862} "352x288"
27 = {Size@11863} "320x240"
28 = {Size@11864} "256x144"
29 = {Size@11865} "176x144"
and we have 12 available sizes in this range
Camera2DeviceSurfaceManager.java:: getPreviewSize()
mCameraSupportedSurfaceCombinationMap.get(cameraId).getSurfaceDefinition().getPreviewSize() = "1920x1080"
cameraId=0
gr...@gmail.com <gr...@gmail.com> #4
The issue root cause is that CameraX will default filter out sizes smaller than 640x480. For Preview, the max size will be limited to under display size. I checked the HW spec info for the issue related devices. Display size of FUJITSU F-04J/F-05J is 360x640. That will result int that no size exists in the conditions that is larger or equal to 640x480 and smaller or equal to 360x640.
A temporary workaround for this situation is to use Preview.Builder#setTargetResolution() to set a size smaller than 640x480 to bypass the problem.
For device FUJITSU arrowsM04, I checked its HW spec info and its display size I found is 1280x720. It seems that the problem should not exist in the device.
Could you confirm that the problem exist on arrowsM04 device? What will be the returned value when using Display#getRealSize to obtain the display size?
wa...@gmail.com <wa...@gmail.com> #5
wa...@gmail.com <wa...@gmail.com> #6
This issue happened on devices that the display size is smaller than 640x480. In original auto-resolution mechanism, supported sizes smaller than 640x480 will be default filter out.
The auto-resolution mechanism encodes the guaranteed configurations tables in CameraDevice#createCaptureSession(SessionConfiguration). It defines that the PREVIEW size is the small one of the device display size and 1080p. The PREVIEW size will be the maximal size limitation for Preview use case. The reason it limits the size to display size and 1080p is the stream output in display size or 1080p has been able to provide good enough preview quality. Therefore, auto-resolution mechanism will limit the selected size to be smaller than the small one of the device display size and 1080p.
With above two conditions, in this issue, all sizes smaller than 640x480 have been filter out, therefore, there is no size smaller than the display size 320x240 can be selected to use. And cause the exception.
Solution:
When the display size is smaller than 640x480, auto-resolution mechanism won't filter out those small sizes smaller than 640x480. This makes those small size be left and can be selected for the Preview use case on small display devices.
The solution has been merged and will be included in next CameraX release.
b9...@gmail.com <b9...@gmail.com> #7
Hello.
This crash still occurs.
- CAMERAX VERSION: 1.0.0-beta4
- ANDROID OS BUILD NUMBER: Android 7.1.1
- DEVICE NAME: FUJITSU F-02H
We receive following crash report from FUJITSU F-02H. So far We have received this crash report only from F-02H.
java.lang.IllegalArgumentException
Can not get supported output size under supported maximum for the format: 34
androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes (SupportedSurfaceCombination.java:349)
androidx.camera.camera2.internal.SupportedSurfaceCombination.getSuggestedResolutions (SupportedSurfaceCombination.java:197)
androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions (Camera2DeviceSurfaceManager.java:198)
androidx.camera.core.CameraX.calculateSuggestedResolutions (CameraX.java:949)
androidx.camera.core.CameraX.bindToLifecycle (CameraX.java:351)
androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle (ProcessCameraProvider.java:230)
(our application's package name).CameraFragment.bindCameraUseCases (CameraFragment.java:174)
wa...@gmail.com <wa...@gmail.com> #8
Could you help to provide the following information to clarify the issue?
1. Is the full name of the device Fujitsu Arrows NX F-02H that has a 1440x2560 display?
2. Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
ez...@gmail.com <ez...@gmail.com> #9
- Is the full name of the device Fujitsu Arrows NX F-02H that has a 1440x2560 display?
Yes
- Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
Since we don't have this device, we'll try to collect this information in the next version of our app. The next version will be released later this month.
gr...@gmail.com <gr...@gmail.com> #10
Hello.
- Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
We have collected the output of the device where the crash occurs.
Device1
- Model : arrows Be F-05J
- Android Version : 7.1.1
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0: 480x480
CameraId 1: 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
Device2
- Model : Fujitsu arrows M04
- Android Version : 7.1.1
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0: 480x480
CameraId 1: 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
Additional Information
CameraX version : 1.0.0-beta04
We collect the supported output sizes by following code.
val errorString = buildString {
append("The supported output sizes of ImageFormat.PRIVATE: ")
(requireContext().getSystemService(Context.CAMERA_SERVICE) as CameraManager).apply {
cameraIdList.forEachIndexed { index, cameraId ->
val msg = if (VERSION.SDK_INT >= VERSION_CODES.M) {
val configurationMap =
getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
val sizes = configurationMap?.getOutputSizes(ImageFormat.PRIVATE)
"CameraId $index: ${sizes?.joinToString(" ,")}"
} else {
"CameraId $index: This device version is under M."
}
append(msg)
}
}
}
os...@gmail.com <os...@gmail.com> #11
wa...@gmail.com <wa...@gmail.com> #12
I tried to find the device specs and both 720x1280
size display. For the camera id 0 device, it is a different case that the display size is larger than 640x480
but the device only supports a 480x480
size. The case also caused the same IllegalArgumentException and was also fixed by 1.0.0-beta04
release. Before 480x480
size would be filtered out and then caused the IllegalArgumentException. After it was merged, the 640x480
size threshold was removed and then the 480x480
size would be kept and selected to use.
It looks like 1.0.0-beta04
release had been used to collect the supported sizes information. But the issue should have been fixed by 1.0.0-beta04
release. Did you only check the device model name to collect the supported sizes information or collect the information when the IllegalArgumentException issue happens again?
CameraX's 1.0.0-beta04
version. Maybe you can also consider to upgrade to the latest 1.0.0-rc01
version for your application. Thanks.
gr...@gmail.com <gr...@gmail.com> #13
Did you only check the device model name to collect the supported sizes information or collect the information when the IllegalArgumentException issue happens again?
We collect informations only from the device on which IllegalArgumentException happened.
Our latest app uses CameraX version 1.0.0-beta10
and this issue still occurres.
However we don't receive crash report from Fujitsu arrows Be F-05J
or Fujitsu arrows M04
so far. (This doesn't mean this issue is fixed on these devices because our app is heavily rely on camera so these device's user wouldn't use our app anymore.)
Instead, we receive crash report from
- Model : Fujitsu F-03K
- Android Version : 7.1.2
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0 : 480x480
CameraId 1 : 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
wa...@gmail.com <wa...@gmail.com> #14
I missed some settings when I simulated the issue by robolectric test so that I was not able to reproduce it. Now, I can reproduce the issue if the device only supports one 480x480 resolution. I'm working on the solution and target to make it included in next release.
gr...@gmail.com <gr...@gmail.com> #15
Branch: androidx-main
commit 69d15dff7bb857ee33a0f643ff42a0f8bc475ab2
Author: charcoalchen <charcoalchen@google.com>
Date: Fri Jan 08 18:30:03 2021
Fixed IllegalArgumentException issue happened when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480.
Do not filter out sizes smaller than 640x480 when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480.
Relnote:"Fixed IllegalArgumentException issue happened when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480."
Bug: 150506192
Test: SupportedSurfaceCombinationTest
Change-Id: I2a63ce8e2ad42a9cc060c8635ac3603bf440b1ec
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
M camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
wa...@gmail.com <wa...@gmail.com> #16
wa...@gmail.com <wa...@gmail.com> #17
val relocationRequestor = remember { RelocationRequester() }
TextField(
modifier = Modifier
.fillMaxWidth()
.relocationRequester(relocationRequestor),
value = person.name,
onValueChange = {
person.name = it
relocationRequestor.bringIntoView()
}
)
This simple code is working unless your text field has too much height because it does not scroll to bring the text field into view according to cursor position !
Since relocationRequester gets the coordinates from onGloballyPositioned Modifier
And sometimes a black rectangle starts appearing in the bottom
po...@gmail.com <po...@gmail.com> #18
oo...@gmail.com <oo...@gmail.com> #19
I'd argue it's more than P4, since this means any bottom-located BasicTextField
in a list will be covered by the keyboard.
The only solution I have is the incredibly hacky solution with a RelocationRequester
courtesy of #17.
val relocationRequester = remember { RelocationRequester() }
val scope = rememberCoroutineScope()
...
BasicTextField("", {},
Modifier
.relocationRequester(relocationRequester)
.onFocusChanged {
if ("$it" == "Active") {
scope.launch {
delay(300)
relocationRequester.bringIntoView()
}
}
},
)
ch...@gmail.com <ch...@gmail.com> #20
I'm also affected by this issue and strongly argue for it being higher than a P4.
This affects almost any use of TextField
s within a scrolling area (depending on screen size).
Maintaining visibility on what a user is typing is, at a high level, a very basic requirement of any UI framework and currently, in Compose, this is simply not working.
Having to apply such a hack solution just so the user can see what they're typing is unacceptable and should be remediated at higher priority than P4.
ma...@gmail.com <ma...@gmail.com> #21
si...@google.com <si...@google.com> #22
Thank you all the comments.
As a side note So P4 is priority unknown or not checked, but not
-not important-.
ch...@gmail.com <ch...@gmail.com> #23
aa...@icloud.com <aa...@icloud.com> #24
It's worth noting that Compose's behaviour is out of sync with Android's view system behaviour.
Compare the below (with <activity android:windowSoftInputMode="adjustResize"....>
enabled) when you click on a bottom-located EditText
(a RecyclerView
version of the below gives the same behaviour)
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayoutandroid:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<EditText
android:text="hi there"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</EditText>
...
</LinearLayout>
</ScrollView>
With
LazyColumn {
items((1..100).toList()) { BasicTextField("$it", {}) }
}
The Android view system version moves the EditText
above the keyboard. The Compose version does not.
ta...@monzo.com <ta...@monzo.com> #25
Just wanted to add another dimension to this issue - it essentially prevents anyone from using a TextField
inside a LazyColumn
. If the activity is resized, but the lazy list doesn't scroll to make the focused TextField
visible when the keyboard is opened, it is recycled - removing the TextField
from the tree and causing the keyboard to close immediately. It's simply unusable.
ma...@voltasit.com <ma...@voltasit.com> #26
lu...@gmail.com <lu...@gmail.com> #27
ar...@gmail.com <ar...@gmail.com> #28
ez...@gmail.com <ez...@gmail.com> #29
Can you share your solution with the others?
Did you just wrap EditText (or TextInputLayout) with a Compose interface?
ja...@gmail.com <ja...@gmail.com> #30
The mentioned hack with relocations now works only with BringIntoViewRequester instead of RelocationRequester and works only for the first time soft-keyboard is opened. Second time and so on - text input hides below keyboard.
OutlinedTextField(
value = text,
modifier = Modifier.bringIntoViewRequester(relocation)
.onFocusChanged {
if (it.isFocused) scope.launch {
delay(300); relocation.bringIntoView() }
}.focusTarget(),
onValueChange = { new -> text = new },
label = { Text("Input here") },
)
Maybe it would works if keyboard options to free the focus after Done or keyboard hiding will be invoked?
ja...@gmail.com <ja...@gmail.com> #31
Ok, the following variant of hack is working each time the keaboard appears!!
val relocation = remember { BringIntoViewRequester() }
val scope = rememberCoroutineScope()
OutlinedTextField(
value = text,
modifier = Modifier.bringIntoViewRequester(relocation)
.onFocusEvent {
if (it.isFocused) scope.launch { delay(300); relocation.bringIntoView() }
},
onValueChange = { new -> text = new },
label = { Text("Input here") },
)
an...@gmail.com <an...@gmail.com> #32
I am not able to use BringIntoViewRequester
- I can't find the library for importing it. I am importing these, but the relocation
package is not visible for me:
implementation "androidx.compose.foundation:foundation-layout:1.0.5"
implementation "androidx.compose.foundation:foundation:1.0.5"
Please, what Compose dependency contains BringIntoViewRequester
and Modifier.bringIntoViewRequester
?
EDIT: Solved - you need to use 1.1.0-beta02
🤦♂️
ja...@deepl.com <ja...@deepl.com> #34
The described workaround doesn't work if using a height constraint multiline TextField
. If the TextField
becomes scrollable and the focus is at the end, the TextField
doesn't scroll correctly, e.g.:
var text by remember { mutableStateOf("") }
Column(modifier = modifier.fillMaxSize()) {
TextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier
.weight(1f)
.background(Color.Gray))
}
Same applies to a TextField
with a verticalScroll
Modifier.
I've attached a video and pushed the code to this repository: keyboard_scroll_bug
)
Note: I use the Accompanist Insets Library, an Android 12 Device (same on Android 7) and the latest Compose Beta (1.1.0-beta04).
ma...@memrise.com <ma...@memrise.com> #35
The solution with BringIntoViewRequester
works well for me (as suggested android:windowSoftInputMode="adjustResize"
:( This is a problem for me, because I've got a sticky button at the bottom of my scroll view, and when the keyboard appears, the button moves on top of the keyboard.
Sure I can hide it when the keyboard is open, but it flashes for a split second on top of the keyboard, still :(
Any idea how to use BringIntoViewRequester
with android:windowSoftInputMode="adjustNothing"
?
pr...@gmail.com <pr...@gmail.com> #36
Dear guys, finally I have a solution for it. Just follow these steps below:
Step 1: In your AndroidManifest.xml
<activity
...
android:windowSoftInputMode="adjustResize">
</activity>
Step 2: In your Activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
AppTheme {
ProvideWindowInsets(
windowInsetsAnimationsEnabled = true,
consumeWindowInsets = false,
) {
// your content
}
}
}
Step 3:
LazyColumn(
modifier = Modifier
.navigationBarsWithImePadding()
.verticalScroll(state = rememberScrollState())
.height(LocalConfiguration.current.screenHeightDp.dp)
.fillMaxWidth(),
) {
// your TextField items
}
Step 4:
// init your CoroutineScope
val coroutineScope = rememberCoroutineScope()
// init your BringIntoViewRequester
val bringIntoViewRequester = BringIntoViewRequester()
// use them in your TextField modifier
modifier = Modifier
/* ... your other modifiers */
.bringIntoViewRequester(bringIntoViewRequester)
.onFocusEvent {
if (it.isFocused || it.hasFocus) {
coroutineScope.launch {
delay(250)
bringIntoViewRequester.bringIntoView()
}
}
}
}
Hope it helps.
sa...@gmail.com <sa...@gmail.com> #37
sa...@gmail.com <sa...@gmail.com> #38
[Deleted User] <[Deleted User]> #39
Can folks kindly desist from posting more 'solutions' that involve requesting focus after a delay. Doing this may be an effective workaround in many situations but it's absolutely not a proper solution. This issue isn't about an implementation bug either; the Compose components are working as designed. Rather, this is a design issue that is probably going to require enhancements to Compose API's to allow scrollables to continuously 'track' visibility on a focused component, not just acquire it instantaneously.
si...@gmail.com <si...@gmail.com> #40
Hello gents, I think I found the best workaround (at least for my needs) to solve this very annoying issue. The only disadvantages of my approach are:
- no animation when scroll the list to make the field visible.
- in some cases a double scroll can be needed to make the field visible.
The second disadvantage currently happens only on my OnePlus 6t,
To implement this behaviour I had to use accompanist insets library. So:
- I added
android:windowSoftInputMode="adjustResize"
in the activity tag in the manifest - I added
WindowCompat.setDecorFitsSystemWindows(window, false)
after super.onCreate() in the activity where the composition happens. - I called
ProvideWindowInsets {}
after the theme and put everything in it. - I provided the appropriate insets modifier in my composable.
The last point depends on the implementation, in my case I have a Scaffold with a TopAppBar and a LazyColumn as content. In the Scaffold (but it could be used in the topAppBar) I applied Modifier.statusBarsPadding()
. In the LazyColumn I applied Modifier.navigationBarsWithImePadding()
. The LazyColumn is as big as the space available in the scaffold (so from the TopAppBar to the bottom of the screen).
Following these steps the insets are correct and the activity is resized when the keyboard is displayed. This cause the issue: If I understood correctly the problem is not the keyboard itself, when the activity is resized the items of the LazyColumn which are cut out from the resize are out from the recomposition as well. So actually the issue is caused by adjustResize flag, but without it we cannot have any hint about the keyboard, which is important to scroll the LazyColumn accordingly. Also without the flag, the behaviour is not the best from the user experience point of view.
So the idea is to scroll the LazyColumn of the amount of pixels needed to keep the field visible. The important thing to notice is that the scroll must be launched (and terminated) as soon as possible, because if the animation of the keyboard is faster, the field is covered and it loose the focus.
When a field is clicked it becomes focused, so I assign its index to state. This calls a recomposition. Thanks to the insets library I can have some info about the keyboard. In particular I can know if the keyboard is visible (true even if it is not completely displayed), the total height and the current height.
On my field and on the LazyColumn I used modifier.onGloballyPositioned{}
to have the knowledge of the position of the composables in the window. So knowing the size of the keyboard and the position of the items in the window I can calculate the exact amount of scroll. But sometimes the field could not scroll. Imagine the last one, on the bottom of the list, since it is the last one, the list is scrolled, so no scroll can be achieved. So I placed an item{}
at the bottom of the list wich contains a spacer. The height of the spacer is total keyboard height - current keyboard height. So at the first frame of the keyboard animation it will be as high as the keyboard, at the end of the keyboard animation or when the keyboard is not visible its height will be 0.
Here the full implementation:
//Manifest file, activity tag:
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.ListTest.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
class MainActivity : ComponentActivity() {
@ExperimentalComposeUiApi
@ExperimentalFoundationApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
ListTestTheme {
Surface(color = MaterialTheme.colors.background) {
UI()
}
}
}
}
}
@ExperimentalComposeUiApi
@ExperimentalFoundationApi
@Composable
fun UI() {
ProvideWindowInsets {
Scaffold(
modifier = Modifier.statusBarsPadding(),
topBar = {
TopAppBar(
backgroundColor = MaterialTheme.colors.surface,
title = {
Text(text = "Test")
},
navigationIcon = {
IconButton(onClick = {
}) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null
)
}
}
)
}
){
//PositionManager is a class which handle the position of the composable views and
//calculate the scroll amount according to the keyboard height. It is defined at the
//bottom of the activity.
val positionManager = remember {
PositionManager()
}
//this is just to have the padding bottom in pixels. The position of the composable views
//doesn't have this information since it is calculated based on the y coordinates plus the
//height. In my case I have different padding depending if the item is the last one or not
val bottom8 = with(LocalDensity.current) { 8.dp.toPx() }
val bottom16 = with(LocalDensity.current) { 16.dp.toPx() }
val insets = LocalWindowInsets.current
val ime = insets.ime
//the total height of the keyboard, 0 when the keyboard is not visible. On my OnePlus 6t
//sometimes this value changes during the animation, this cause the double scroll effect
val keyboardSize = ime.layoutInsets.bottom
//on any recomposition I set the keyboard size here. This is because as I said on some
//devices the final keyboard size value can change during the animation
positionManager.setCurrentHeight(keyboardSize)
val listState = rememberLazyListState()
var focusIndex by remember {
mutableStateOf(-1)
}
if(focusIndex != -1 && ime.isVisible){
LaunchedEffect(key1 = keyboardSize, ime.isVisible){
val amount = positionManager.getScrollAmount(focusIndex) -
insets.navigationBars.bottom
//important!! the scroll cannot be animated. If the animation of the keyboard is
//faster than the animation of the scroll (and it happens on samsung devices where
//the keyboard is basically not animated, the field goes out of the composition.
if(amount > 0) listState.scrollBy(amount)
}
}
LazyColumn(
modifier = Modifier
.fillMaxSize()
.navigationBarsWithImePadding()
.onGloballyPositioned {
//The parent is important to calculate the scroll amount since the resizing of
//the activity cuts it
if (!positionManager.isParentSet)
positionManager.setupParent(it)
},
contentPadding = it,
state = listState
){
items(20){ index ->
val modifier = Modifier
.padding(
start = 16.dp,
end = 16.dp,
top = if (index == 0) 16.dp else
8.dp,
bottom = if (index == 19) 16.dp else
8.dp
)
.onGloballyPositioned {
//the position of the field, which is updated in the PositionManager when
//needed
if (!ime.animationInProgress || ime.animationInProgress && index ==
focusIndex) {
positionManager.registerPosition(
index,
//bottom16 and bottom8 are the padding in pixels, on my case since
//I added just 20 elements, I'm using the padding checking the
//index, of course this is not a good approach since the index is
//hardcoded
PositionHandler(it, if (index == 19) bottom16 else bottom8)
)
}
}
.onFocusChanged {
if (it.isFocused) {
//update the state. this is important because I need to know the index
//of the field, but also because this trigger a recomposition before
//the keyboard is displayed, so at the very first frame of the
//keyboard animation
focusIndex = index
}
}
.fillMaxWidth()
Item(
modifier = modifier,
index = index,
editable = true
)
}
item {
//this adds some scrollable space at the bottom of the lazycolumn to make it
//scrollable during the keyboard animation even when the field which is going to
//be focused is the last one
Spacer(modifier = Modifier.height(with(LocalDensity.current) {
(keyboardSize - ime.bottom).toDp()
}))
}
}
}
}
}
@Composable
fun Item(
modifier: Modifier = Modifier,
index: Int,
editable: Boolean
){
OutlinedTextField(
modifier = modifier,
value = index.toString(),
onValueChange = {},
readOnly = !editable
)
}
//this class handle all the PositionRelated behaviour, calculating the scroll amount and even the new //scroll amount if the total keyboard height value changes during the animation
class PositionManager {
private val positions = HashMap<Int, PositionHandler>()
private lateinit var parent: LayoutCoordinates
var isParentSet = false
private set
private var currentHeight: Int = 0
private var scrollToConsumeForKeyboard: Float = 0F
fun setupParent(layoutCoordinates: LayoutCoordinates){
parent = layoutCoordinates
if(parent.size.height != 0)
isParentSet = true
}
fun registerPosition(index: Int, positionHandler: PositionHandler){
positions[index] = positionHandler
}
fun getScrollAmount(index: Int): Float{
return positions[index]?.calculateOffset(scrollToConsumeForKeyboard, parent, scrollToConsumeForKeyboard == currentHeight.toFloat()) ?: 0F
}
fun setCurrentHeight(currentHeight: Int){
scrollToConsumeForKeyboard = if(this.currentHeight != 0 && currentHeight != 0 && this.currentHeight != currentHeight){
(currentHeight - this.currentHeight).toFloat()
} else currentHeight.toFloat()
this.currentHeight = currentHeight
}
}
class PositionHandler(
layoutCoordinates: LayoutCoordinates,
private val paddingBottomPx: Float
){
private val bottom = layoutCoordinates.boundsInWindow().bottom
fun calculateOffset(keyboardHeight: Float, parent: LayoutCoordinates, consumePadding: Boolean): Float{
val parentBottom = parent.boundsInWindow().bottom
val newBottom = parentBottom - keyboardHeight
return bottom - newBottom + if(consumePadding) paddingBottomPx else 0F
}
}
I hope I was enough clear, english is not my native language :)
co...@protonmail.com <co...@protonmail.com> #41
For what it's worth, I'm not having this issue anymore. No need for artificial delays or anything.
(This was an issue for me when I used compose pre-1.0, but now I'm using compose 1.1.0-RC01)
This is what I'm doing (using accompanist inset lib)
<activity
...
android:windowSoftInputMode="adjustResize"> <===You need this as per accompnist inset docs
</activity>
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false) <=== I do this so my app looks modern and edge to edge
setContent {
AppTheme {
ProvideWindowInsets(
) {
//content
}
}
}
LazyColumn( modifier = Modifier .navigationBarsWithImePadding() .fillMaxWidth(), ) { // TextField items }
co...@protonmail.com <co...@protonmail.com> #42
I spoke too soon. It worked in an emulator, but didn't scroll up automatically on my physical pixel 6.
si...@gmail.com <si...@gmail.com> #43
Yeah, when I read your post I thought that there were some fixes in the 1.1.0-RC01, but it doesn't work.
co...@protonmail.com <co...@protonmail.com> #44
For what its worth. I spent the entire day trying out all of the solutions above with no luck.
If anyone can figure out how to put 20 field inputs in a column (either scrollable or LazyColumn) and you can hit the ImeAction.Next button and scroll through all the items... please let me know. =)
si...@gmail.com <si...@gmail.com> #45
You have to do it manually. If you read my solution (comment 40) I calculated the exact amount of scroll needed based on the size of the single item, of the lazycolumn and of the keyboard. You can adapt the code to manually scroll of that amount when you hit the keyboard button
wa...@gmail.com <wa...@gmail.com> #46
Bring Into View Requester takes a rect , I would like to give it offset , let's say there another composable that needs to be always visible above the IME like a footer with buttons like in text editor applications , Now that composable might come above the text field when staying above the IME and the current line user is writing is underneath that footer thingy ! I wish I could provide offsets and move the text field more into y direction than it needs to , as much needed for my footer to always by visible below the text field and above the IME
co...@protonmail.com <co...@protonmail.com> #47
@si...@gmail.com OH! I thought your comment did handle the keyboard button. I guess I will give it another try. Not to give you more work... but if there any chance you could get a working repo of this up on github. Might be slightly easier to follow your code along there. I will try to give your idea a whirl when I get back to my desk.
tr...@gmail.com <tr...@gmail.com> #48
Has anyone tried it out yet? And why hasn't someone from Google reported on this here yet?
br...@gmail.com <br...@gmail.com> #49
RE #48... That looks like a different issue. The issue here is that when the ime slides into view, the textfield is not scrolled up and into view (so that you can see what you are typing)
The issue that is fixed in 1.2 looks to be an issue where the cursor doesn't properly scroll out of view when you scroll. That issue is here:
ed...@gmail.com <ed...@gmail.com> #50
Just came across this issue as well. BringIntoViewRequester()
/ bringIntoView()
still broken for me in 1.2.0-alpha01
Only work with delay and even then only 1 time or after focusing different text fields first.
UGH!
nu...@gmail.com <nu...@gmail.com> #51
Compose is causing so much pain in all UX-things. It is not clear why 1.0.0+ is called "stable", if it is still impossible to сomplete default tasks, which were solved very simply for 10 years.
Obviosly it's a lie that there is less code or that it speeds up development - everything is in so raw state, so with this you can only write "hello world" apps or simple pets.
In production you cannot tell clients "Sorry, its P4 in google list. Wait another year or two :)".
pr...@intercom.io <pr...@intercom.io> #52
Issues like this make people really skeptical of using what you call "stable" and drastically slow down adoption.
kl...@google.com <kl...@google.com>
kl...@google.com <kl...@google.com> #53
The main issue was that notifyFocusedRect
was only asking the view to show the rect, not using Compose's mechanism for this, BringIntoViewRequester
.
There's also an issue specifically with lazy lists, where if the field is too low, when the IME shows it disposes the composition containing the field before it has a chance to be brought into view. Once this bug is fixed, the lazy list issue should be fixed once lazy lists are able to keep focused nodes in the composition even when scrolled out of view (
The fix involves implementing
Note this is similar, but I think different than
WIP CL that will eventually contain the fix:
to...@gmail.com <to...@gmail.com> #54
For the record I do not think it was reported in this thread, but there's also a side case, where the scroll does work, but when the keyboard change it's size there's nothing happening. Like the GBoard, you click on a field it scroll, the keyboard is visible, then a top bar on the keyboard is shown with suggestions and it appears over of the field.
kl...@google.com <kl...@google.com> #55
The investigation last week turned up a number of cases we weren't handling, and some were easier to fix than others. ADJUST_PAN
, but for ADJUST_RESIZE
we need to implement a piece of focus infrastructure that doesn't exist yet (
ap...@google.com <ap...@google.com> #56
Branch: androidx-main
commit 22f05f8acfc4a9dfd93a00c537708f26ae8dbe4e
Author: Zach Klippenstein <klippenstein@google.com>
Date: Tue Feb 01 12:27:01 2022
Set focused child before granting it focus.
Fixes a bug where if an onFocusEvent searched for the active FocusModifier
it would crash because the newly-focused child hadn't been set on the
parent modifier yet.
Also cleaned up some code comments in related files – scout rule!
Bug:
Bug:
Test: ./gradlew :compose:ui:ui:cDAT
Change-Id: I1ba0a3411cb3793099b12913a25a8b0d92f74c40
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindFocusableChildrenTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusTestUtils.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
ap...@google.com <ap...@google.com> #57
Branch: androidx-main
commit 314a8bd718c5c905444bc538c6d04e3a4805d848
Author: Zach Klippenstein <klippenstein@google.com>
Date: Wed Feb 02 09:54:40 2022
Fix a bunch of flaky tests caused by performing focus operations off the UI thread.
Bug:
Bug:
Test: Tests are fixed.
Change-Id: I15ee7001a1128486939c273434ef28a41d84ed79
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalThreeItemsTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusTraversalTwoItemsTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CustomFocusTraversalTest.kt
ap...@google.com <ap...@google.com> #58
Branch: androidx-main
commit 1237c1570308c6a5ad043702f5e9051c1c874602
Author: Zach Klippenstein <klippenstein@google.com>
Date: Thu Jan 27 19:41:29 2022
Report AndroidComposeView's focus rect to the view system.
ViewRootImpl controls panning when the keyboard is shown and the window
is configured to pan instead of resize. When it does this, it finds the
focused view and calls getFocusedRect to find the area to keep above the
keyboard. Because Compose has its own internal focus, it needs to report
that to the view system by overriding getFocusedRect in order to be
moved when the keyboard is shown.
I also factored out the keyboard helper methods from
CoreTextFieldSoftKeyboardTest so I could use them for the scrollable
tests.
Bug:
Bug:
Test: ./gradlew :compose:f:f:cDAT
Relnote: "TextFields will now be kept above the keyboard when they are
focused and the keyboard is shown, when the soft input mode is
`ADJUST_RESIZE`."
Change-Id: I8eaebb684b7828dcf92b0678a86d796b49b349c8
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldSoftKeyboardTest.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
A compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextFieldKeyboardScrollableInteractionTest.kt
A compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextFieldsInScrollableDemo.kt
A compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusViewInteropTest.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt
A compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/KeyboardHelper.kt
ap...@google.com <ap...@google.com> #59
Branch: androidx-main
commit a5c92f31181087df9a6a7100111d4248b94e75d4
Author: Zach Klippenstein <klippenstein@google.com>
Date: Fri Jan 28 12:36:11 2022
Change CoreTextField to use BringIntoViewRequester.
CoreTextField needs to ensure the cursor is in the visible bounds of all
scrollable parents, including the one in the text field itself.
Originally, it tried doing this by going through some of the text
service abstractions and ultimately calling
`View.requestRectangleOnScreen`. However, composable parents also need
to be aware of the request, so the correct way to do this is to use the
relatively recent `BringIntoViewRequester`. I'm not sure why all the
indirection through text services was done, it isn't necessary and
obscures the code, so I just made `CoreTextField` directly call
`BringIntoViewRequester.bringIntoView()`. This helps with
but doesn't completely fix it, due to
Bug:
Fixes:
Test: Tested manually.
Test: Refactored TextFieldDelegate unit tests to use the new code path:
./gradlew :compose:f:f:test
Relnote: "`notifyFocusedRect` methods in `TextInputSession` and
`TextInputService` are now deprecated and won't be called. Use
`BringIntoViewRequester` instead."
Change-Id: Ia4302c5f6ee79eec30a9f42c149da8775e1ed57e
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
M compose/ui/ui-text/api/restricted_current.txt
M compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextFieldToggleTextTestCase.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
A compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text/TextFieldBringIntoViewTest.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldDelegate.kt
M compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreTextField.kt
M compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text/TextFieldDelegateTest.kt
M compose/ui/ui-text/api/public_plus_experimental_current.txt
M compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt
M compose/ui/ui-text/api/current.txt
ap...@google.com <ap...@google.com> #60
Branch: androidx-main
commit b47ac54b27a3e77b40f672cbcd5a713f464a4d27
Author: Zach Klippenstein <klippenstein@google.com>
Date: Thu Feb 03 12:09:04 2022
Revert removing implementations of notifyFocusedRect.
The notifyFocusedRect methods on TextInputService and TextInputSession
were deprecated and had their implementations replaced by no-ops in the
change aosp/1959647. This was probably too aggressive, so this change
adds the old implementations back in but leaves them deprecated, in case
any third-party code was calling them. The implementations were actually
broken before, and this change doesn't try to fix them, it just restores
the previous broken behavior.
Discussion thread about revert:
Bug:
Bug:
Test: Old tests restored.
Change-Id: I385749b629fd35b72bd148122ab1ec0f6d4ffa96
M compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/TextInputService.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
M compose/ui/ui-text/src/test/java/androidx/compose/ui/text/TextInputServiceTest.kt
[Deleted User] <[Deleted User]> #61
il...@gmail.com <il...@gmail.com> #62
v....@gmail.com <v....@gmail.com> #63
It is probably fixed in
gu...@googlemail.com <gu...@googlemail.com> #64
I just tried it out. In a single text field it works now. But when I use for example two text fields and on IME action next on the first one I switch the focus to the next field via FocusRequester, the keyboards stays below the first text field and therefore hides the next one.
My assumption would have been that the keyboard would now automatically jump to the next, now focused field.
re...@gmail.com <re...@gmail.com> #65
I guess the problem was partially fixed, tested on version
Here are a few problems:
- The TextField does not get fully visible when using ImeAction (Previous or Next) and focusing in a TextField that is hidden under the keyboard
- The TextField does not get fully visible when the user types on the keyboard.
- Considering the scenario that the TextField was visible when focused, and the user scrolls the screen and start typing while the focused TextField is hidden.
il...@gmail.com <il...@gmail.com> #66
hi...@gmail.com <hi...@gmail.com> #67
I think there is a mistake on the release note of
The release notes say that the behavior of adjustResize
has been improved, but I think this is a mistake for adjustPan
.
According to adjustResize
, but that task still seems to be a
I actually tried it with the accompanist sample, but it only works well with adjustPan
.
Added on 2022/03/02
I just looked at the release notes, and the description is now fixed. Thanks to the person who fixed it.
ap...@google.com <ap...@google.com> #68
Branch: androidx-main
commit 0de2359ab6335c7680e54cdd7b7bae046df9cdae
Author: Zach Klippenstein <klippenstein@google.com>
Date: Tue Feb 22 18:59:29 2022
Update TextFieldsInScrollableDemo to enable toggling setDecorFitsSystemWindows.
Bug:
Bug:
Bug:
Test: manual, since this is just a demo change.
Change-Id: I94deb16188232d8fe2d87b97b27dd3b7f2d36f68
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextFieldsInScrollableDemo.kt
ap...@google.com <ap...@google.com> #69
Branch: androidx-main
commit 30ab5ff0d1840570f5628d9489b47ce118caa4a3
Author: Zach Klippenstein <klippenstein@google.com>
Date: Sat Jan 29 09:36:44 2022
Introduce onFocusBoundsChanged.
Design doc:
Note that this feature does not currently work with AndroidView (
that needs to be wired up in the ui module but this API is needed to fix
an issue in foundation, and I want to leave it as Experimental for now,
and we don't allow cross-module experimental access. When this modifier
is stabilized, it should be moved to UI, and that bug resolved.
Bug:
Bug:
Bug:
Test: Manual via FocusedChildDemo
Test: ./gradlew :compose:f:f:cDAT
Relnote: "Introduced experimental `Modifier.onFocusedBoundsChanged` to allow
observing the bounds of child focusables."
Change-Id: I14283393b5273527ab65f4aa1a2d4383321b0d95
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
M compose/foundation/foundation/api/public_plus_experimental_current.txt
M compose/foundation/foundation/api/current.txt
M compose/foundation/foundation/api/restricted_current.txt
A compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/FocusedBounds.kt
A compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FocusedBoundsDemo.kt
A compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/FocusableBoundsTest.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
sa...@gmail.com <sa...@gmail.com> #70
<activity android:windowSoftInputMode="adjustResize">
Column(modifier = Modifier.wrapContentHeight().navigationBarsWithImePadding())
pa...@7p-group.com <pa...@7p-group.com> #71
Concerning that workaround:
You can get rid of that hacky delay
with an OnGlobalLayoutListener
which will observe the actual IME rect size and will be triggered when the soft keyboard is fully visible.
A basic example could look like this:
val bringIntoViewRequester = remember { BringIntoViewRequester() }
val scope = rememberCoroutineScope()
val view = LocalView.current
DisposableEffect(view) {
val listener = ViewTreeObserver.OnGlobalLayoutListener {
scope.launch { bringIntoViewRequester.bringIntoView() }
}
view.viewTreeObserver.addOnGlobalLayoutListener(listener)
onDispose { view.viewTreeObserver.removeOnGlobalLayoutListener(listener) }
}
OutlinedTextField(
modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester),
...
)
However additional view logic will be needed for it to work with multiple TextField
s.
¯\_(ツ)_/¯
te...@gmail.com <te...@gmail.com> #72
I'm currently using the following workaround :
@OptIn(ExperimentalFoundationApi::class)
// TODO Remove this workaround once they fix the issue
fun Modifier.bringIntoViewOnFocus(
source: MutableInteractionSource? = null,
extraOffset: Float = 0f,
): Modifier = composed {
var layoutCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
val requester = remember { BringIntoViewRequester() }
val isKeyboardShown = LocalWindowInsets.current.ime.isVisible
val isSourceFocused = source?.collectIsFocusedAsState()?.value ?: false
val focusModifier = when (source) {
null -> {
val scope = rememberCoroutineScope()
Modifier.onFocusEvent { state ->
if (state.isFocused && isKeyboardShown) {
scope.launch {
requester.bringIntoView(layoutCoordinates, extraOffset)
}
}
}
}
else -> Modifier
}
if (isSourceFocused && isKeyboardShown) {
LaunchedEffect(Unit) {
requester.bringIntoView(layoutCoordinates, extraOffset)
}
}
Modifier
.onGloballyPositioned { layoutCoordinates = it }
.bringIntoViewRequester(requester)
.then(focusModifier)
}
@OptIn(ExperimentalFoundationApi::class)
private suspend fun BringIntoViewRequester.bringIntoView(
coordinates: LayoutCoordinates? = null,
offset: Float = 0f,
) {
val position = coordinates?.size?.toSize()?.toRect()
val adjusted = position?.copy(
top = position.top + offset,
bottom = position.bottom + offset
)
bringIntoView(adjusted)
}
You can pass in MutableInteractionSource
or it will default to Modifier.onFocusEvent
+ an extra offset in case the bottom navigation gets in the way. I'm sure it's not the best solution but it seems to work ok.
Usage :
val extraOffset = with(LocalDensity.current) {
BottomHeight.toPx()
}
OutlinedTextField(
value = "test",
onValueChange = { },
modifier = Modifier.bringIntoViewOnFocus(extraOffset = extraOffset),
)
ap...@google.com <ap...@google.com> #73
Branch: androidx-main
commit d9c6260e0ecaab7b33ecda95611d60e3184a0fa4
Author: Zach Klippenstein <klippenstein@google.com>
Date: Mon Jan 31 09:46:32 2022
Make scrollable keep focused view in view when resized.
This is part of the fix for these bugs, another other part is aosp/1964580.
This behavior still doesn't work as expected for lazy lists because the
focused item can be removed due to the resize before it has a chance to
be scrolled into view. Ralston's working on the necessary functionality
to fix this.
Design doc:
Bug:
Bug:
Fixes:
Test: ./gradlew :compose:f:f:cDAT
Relnote: "Scroll modifiers (`Modifier.verticalScroll()`,
`Modifier.horizontalScroll()`, and `Modifier.scrollable()`)
will now scroll to keep the focused composable visible if
the scroll area is resized and the focused composable was
previously visible."
Relnote: "TextFields will now be kept above the keyboard when they are
focused and the keyboard is shown, when inside a non-lazy
scrollable and the soft input mode is `ADJUST_RESIZE`."
Change-Id: I4a485a1c80aa2d500dcd55e916006903ff45da95
A compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableFocusableInteractionTest.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
A compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ScrollableFocusedChildDemo.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
cr...@gmail.com <cr...@gmail.com> #74
ni...@gmail.com <ni...@gmail.com> #76
I still have issue with 1.2.0-alpha05, ADJUST_PAN and Landscape Orientation :
@Composable
private fun Screen() {
var textValue by remember {
mutableStateOf("")
}
Surface(Modifier.fillMaxSize()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize()
) {
Text(
text = "Title",
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Start,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.3f)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "Text\nTwo line",
style = MaterialTheme.typography.body2,
textAlign = TextAlign.Start,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.2f)
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
textStyle = MaterialTheme.typography.body2,
value = textValue,
onValueChange = {
textValue = it
},
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Blue,
textColor = MaterialTheme.colors.onSurface,
focusedIndicatorColor = MaterialTheme.colors.onSurface,
unfocusedIndicatorColor = Color.Transparent,
cursorColor = MaterialTheme.colors.onSurface
)
)
}
}
}
Click on the TextField and the field will be behind the keyboard. Be sure to force the orientation in landscape :
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|uiMode|screenSize|screenLayout|orientation|colorMode|density|fontScale|fontWeightAdjustment|keyboard|layoutDirection|locale|mcc|mnc|navigation|smallestScreenSize|touchscreen"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="landscape"
android:theme="@style/Theme.ComposeTextFieldLandscapeTest"
android:windowSoftInputMode="adjustPan">
Is it expected or still a bug ? It works if we adjust a vertical padding on Column (basically if the TextField is small "enough", it will be displayed above the keyboard). Maybe the issue is that the field is too big to be displayed above so it doesn't "scroll" to it ?
I'll push my sample on Github if required.
li...@gmail.com <li...@gmail.com> #77
What is the recommended workaround for this issue? I tried some of the ones posted above but it seems they have limitations and do not always work in my case.
co...@protonmail.com <co...@protonmail.com> #78
The fix should be in for non-lazy column in 1.2.0-alpha06
As per
"TextFields will now be kept above the keyboard when they are focused and the keyboard is shown, when inside a non-lazy scrollable and the soft input mode is ADJUST_RESIZE. (I4a485,
an...@gmail.com <an...@gmail.com> #79
I have this in the manifest:
<activity
android:windowSoftInputMode="adjustResize"
The Composable is inside a non-lazy scrollable like this:
Column(Modifier.verticalScroll(rememberScrollState())) {
OutlinedTextField(.....
Am I missing something else to get it to work?
be...@yescapa.com <be...@yescapa.com> #80
Or it is still required by accompagnist for edge to edge effect.
Am I missing something?
I checked the sample :
compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextFieldsInScrollableDemo.kt
And it's not working properly neither when setting off decor fits system windows and keyboard to ADJUST_RESIZE.
sl...@gmail.com <sl...@gmail.com> #81
My layout is
==== Header ====
--- scrollable column ---
==== Bottom Bar ====
If I set WindowCompat.setDecorFitsSystemWindows(window, false) then the text field in the scrollable column doesn't stay on screen
If I remove WindowCompat.setDecorFitsSystemWindows(window, false) and have ADJUST_RESIZE then the bottom controls are not covered by the IME
jo...@gmail.com <jo...@gmail.com> #82
ni...@google.com <ni...@google.com> #83
Compose status update: Please update the Status
and Status Summary
fields of this bug! (or Public Status
/Public Status Summary
)
te...@gmail.com <te...@gmail.com> #84
1.2.0-alpha07
works for me even with WindowCompat.setDecorFitsSystemWindows(window, false)
- I'm listening for insets in the activity and adding the ime ones as a bottom padding for the content FrameLayout findViewById(android.R.id.content)
.
My only question is how to specify an extra offset to scroll additionally when keyboard appears? Say you have a bottom navigation that may get in the way or implemented toolbar quick return pattern as the user scrolls and using offset on the scaffold content?
to...@gmail.com <to...@gmail.com> #85
kl...@google.com <kl...@google.com> #86
I can repro the case where adding newlines until the cursor goes below the IME does not cause a scroll, but that's a separate issue so I've filed it as
I can't repro the issue reported in #81. What device/android version/IME are you seeing this with?
ni...@gmail.com <ni...@gmail.com> #87
Should I report #76 in another issue ? it still happens in 1.2.0-alpha07 ; basically the text still goes below the IME if the TextField is too large to be visible entirely in the Rect above the IME. I have a working sample in the comment.
kl...@google.com <kl...@google.com> #88
Isn't that the same as
kl...@google.com <kl...@google.com> #89
Ok I can repro #81 on my Pixel 3 – ADJUST_RESIZE
, not fitting system windows. Will investigate.
kl...@google.com <kl...@google.com> #90
Filed the issue in #81 as
nu...@gmail.com <nu...@gmail.com> #91
Looks like compose won't be usable in production in another next year.
di...@gmail.com <di...@gmail.com> #92
This is unfair. Compose issues are getting worked on, and at a good pace (contrary to many AOSP core bugs).
This one was one of the more complex ones and I guess it was delayed due to priorities which to me seem more or less reasonable.
And Compose is very usable in production, we have already released several rather complex apps which use it extensively.
nu...@gmail.com <nu...@gmail.com> #93
What you doing, when QA, or (which is more scare) customer report that as problem? Tell them about other's p4 priorities on meetaps? Even when there are examples nearby that do not have such problems?
I'm even not talking about dozens of wasted hours to discover that there are no workarounds.
And users see that and treating it as a your bug. All of that lead to reputation loss at best.
We're talking about edittext, one of the basic elements for building a view. And it's problematic. As profesiional, i dont want to build to my customers buildings form crumbling bricks, whose manufacturer says "i fix it... well, maybe after all other things. Not important". I build it from bricks without that problems (because there are many problems other than multiline text editing)
On current stage compose is too fraught with loss of reputation, time and money, when you discover that things, no one which talking about in their "i use compose, and my life became better, hair became thicker, and blablabla" articles. And things gets even worse, when its you who advise command start new project on this. Problems and delays start to scale.
Its just not practical to waste no yourself money/time, no money of people, which paid your fo work and solutions.
di...@gmail.com <di...@gmail.com> #94
All issues we've run into with QA (including this one) were fixable with workarounds. Also Compose devs provide good support/advice on them in kotlinlang's slack #compose channel. And doing workarounds for Compose issues is a lot more easier/pleasant than doing ones for a View-based system.
Anyways, I think this is not the discussion for the issue tracker.
sa...@gmail.com <sa...@gmail.com> #95
it's not production ready at all. also adding workaround is not easy.
If you are using some framework, it should work as expected.
You shouldn't learn internals of that framework and work lots of days to fix issues in framework.
This edit text and keyboard behaviour is a basic thing.
They should have moved it to stable only after fixing such basic issues.
They are hurried up. Some internal politics probably. CameraX is a good example.
They have kept it in beta for a long time. Like that, they should have kept compose in beta until those issues are getting resolved.
sk...@gmail.com <sk...@gmail.com> #96
Powerful tools may come with a bit of a steep learning curve (and to be honest, Compose ain't all that hard), but once that's done, you benefit from amazing possibilities and powers.
Regarding bugs, I don't see how Compose is any more buggy than the View system. As with any complex project, bugs are simply inevitable. It is indeed a new thing, and may still need some work to mature, but that's why there's Compose/View interop.
I use Compose mainly and I barely have to fix anything. If I don't like a default behavior, I don't have to sift through a 1000-line Custom View Java file, but I can simply copy the underlying Composable function, which is usually very simple and easy to understand, and change whatever I want easily.
And yes, I've already produced some rather complex apps with Compose, and actually used it for some weird use cases that I think are simply too hard to be worth it with Views, and yet Compose helped me create them reliably and easily exactly as I wanted (and even more than I wanted) down to individual pixels and even the small nuances in animations, shapes, and behavior, with code that's maintainable, short, and dare I say it, beautiful.
And at the end of the day, if you don't like it, don't use it. Google did not force anyone to use Compose, and all of its hype is well-deserved, aired by the Android Developer community at large.
Anyways, this is not the place to fight over this. If you have anything to help with this specific issue, you're welcome to provide your feedback. Otherwise you can go on Twitter or Reddit and do destructive criticism as much as you please, while developers here are building the next big thing.
kl...@google.com <kl...@google.com> #97
I don't have any updates about fixes yet, but I understand the frustration about this issue and it is definitely being worked on. It's not actually a P4 – the "Priority" field on buganizer is very misleading, it has a very specific internal meaning and interaction with other systems so we don't use it for actual prioritization for compose text issues. Unfortunately, the way we track actual priority is not visible externally.
sa...@gmail.com <sa...@gmail.com> #98
ja...@gmail.com <ja...@gmail.com> #99
sh...@gmail.com <sh...@gmail.com> #100
//Library
implementation("com.google.accompanist:accompanist-insets:0.24.9-beta")
//Add this to your activity In AndroidManifest
android:windowSoftInputMode="stateVisible|adjustResize">
//Just add contentPadding in LazyColumn as -
LazyColumn(
contentPadding = rememberInsetsPaddingValues(
insets = LocalWindowInsets.current.systemBars,
applyTop = true,
applyBottom = true,
)
) {
//TextField and other widgets
}
bl...@gmail.com <bl...@gmail.com> #101
I'm using 1.2.0-beta03
and trying to make this work for a TextField
inside a Row
.
Even while using one of the workarounds, the functionality doesn't work most of the time in landscape mode, and seems to not work in certain cases in portrait mode (perhaps when the keyboard pops up a second or later time and making certain types of edits).
@OptIn(ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class)
@Composable
fun EnterText() {
Row(
modifier = Modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
)
{
val relocation = remember { BringIntoViewRequester() }
val scope = rememberCoroutineScope()
var thoughts by rememberSaveable { mutableStateOf("") }
TextField(
value = thoughts,
modifier = Modifier
.weight(1f)
.bringIntoViewRequester(relocation)
.onFocusEvent {
if (it.isFocused) scope.launch { delay(300); relocation.bringIntoView() }
},
label = { Text(text = "Enter text") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
onValueChange = { newText ->
thoughts = newText
}
)
}
}
xa...@gmail.com <xa...@gmail.com> #102
kl...@google.com <kl...@google.com> #103
Nothing to announce yet, but we are working very actively on this.
ab...@gmail.com <ab...@gmail.com> #104
Please try to fix this on Priority, as going for hit & trial several times with the code and even after that not getting the expected workable solution is frustrating.
he...@gmail.com <he...@gmail.com> #105
wi...@azimo.com <wi...@azimo.com> #106
si...@gmail.com <si...@gmail.com> #107
Read the comment number 40. I use this workaround in production, with about 1M users.
da...@gmail.com <da...@gmail.com> #108
I realized I never posted my workaround for this.
It's actually on an old version of Compose but used to work very reliably
val relocationRequester = remember { RelocationRequester() }
var focused by remember { mutableStateOf(false) }
val ime = LocalWindowInsets.current.ime
LaunchedEffect(focused) {
if (focused) {
var done = false
while (!done) {
if (ime.isVisible && !ime.animationInProgress) {
relocationRequester.bringIntoView()
done = true
}
delay(100L)
}
}
}
TextField(
modifier = Modifier
// ...
.onFocusChanged { focused = it }
// ...
)
I'm not sure if it still works with latest version because I didn't need it in recent projects yet and I haven't been working on the other one for several months.
I first posted it in this slack conversation
ar...@gmail.com <ar...@gmail.com> #109
xa...@gmail.com <xa...@gmail.com> #110
re...@googlemail.com <re...@googlemail.com> #111
wa...@gmail.com <wa...@gmail.com> #112
Let's say I have a sticky footer (bottom navigation) , Now when I type the text field will go below the bottom navigation even though I want it to be above it , so please fix that as well !
st...@google.com <st...@google.com> #113
#112 you think it's worth creating a new issue with a repro on that and we can link to this bug if they're related? just to add to the test cases to verify
wa...@gmail.com <wa...@gmail.com> #114
#113 Yeah , great !
wa...@gmail.com <wa...@gmail.com> #116
I have a question , Do I need to use BringIntoViewRequester or the textfield will be kept in view without me writing any code ? Like Do I need to do anything ?
il...@gmail.com <il...@gmail.com> #117
il...@gmail.com <il...@gmail.com> #118
st...@google.com <st...@google.com> #119
Hi there. This issue is not dead, and it is not fixed in production yet. It remains high priority for us and we're actively working on fixing it. However it is caused by a very complex combination of dependencies and the fix is not trivial. We've most recently been focusing on
ap...@google.com <ap...@google.com> #120
Branch: androidx-main
commit 7e77bb541331ce0d62cabad732e43eca41ac978a
Author: Zach Klippenstein <klippenstein@google.com>
Date: Wed Jul 06 11:42:21 2022
Move BringIntoView queueing into the scrollable implementation.
This change removes the over-complicated coroutine-based queuing of
bringIntoView requests in the BringIntoViewResponder, which now is only
responsible for dispatching the request to the actual responder
interface and propagating it up the modifier local chain.
This gives the actual responder implementation (i.e. in
Modifier.scrollable) all the information about conflicting
requests and manage the queue of ongoing requests with an actual,
explicit queue that is much more straightforward than the previous
coroutine job chaining mess. Each request is stored in an actual list
along with the continuation from the request, and requests are
explicitly resumed or cancelled when needed. This also makes debugging
easier, because there's an actual queue data structure we can inspect,
which contains all the actual information about each request.
It also completely changes how the scroll animation is performed.
On every frame, the scroll target is recomputed to account for
changes in the viewport size, the request size, or the set of active
requests since the last frame, while still keeping the animation
smooth. The animation logic is in its own class, which allows a single
suspend animation call to animate to a target value that can be updated
while the animation is running.
While this change is a valuable cleanup on its own, it also fixes
focused child tracking with an explicit API for keeping a thing in view.
Fixes:
Bug:
Bug:
Bug:
Bug:
Test: ScrollableFocusableInteractionTest
Test: androidx.compose.foundation.relocation.*
Test: RebasableAnimationStateTest
Test: BringIntoViewRequestPriorityQueueTest
Relnote: "Rewrote the way scrollables respond to
`bringIntoViewRequesters` and focusables to better model the
complexity of those operations and handle more edge cases."
Change-Id: I2e5fec8c8582a8fe1f191e37fd0f4f9165678664
M compose/foundation/foundation/api/current.txt
M compose/foundation/foundation/api/public_plus_experimental_current.txt
M compose/foundation/foundation/api/restricted_current.txt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/FoundationDemos.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/ScrollableFocusedChildDemo.kt
A compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/relocation/BringIntoViewResponderDemo.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/relocation/BringRectangleIntoViewDemo.kt
M compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/BringIntoViewSamples.kt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollableFocusableInteractionTest.kt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListFocusMoveTest.kt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponderTest.kt
M compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/relocation/BringIntoViewScrollableInteractionTest.kt
A compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/BringIntoViewRequestPriorityQueue.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/ContentInViewModifier.kt
A compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/UpdatableAnimationState.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/relocation/BringIntoViewResponder.kt
A compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/BringIntoViewRequestPriorityQueueTest.kt
A compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/UpdatableAnimationStateTest.kt
kl...@google.com <kl...@google.com> #121
Major fixes to this were just released in 1.4.0-alpha04. Text fields in lazy columns should work now too. One notable case that is still being worked on is if
ja...@gmail.com <ja...@gmail.com> #122
ATAL EXCEPTION: main
Process: com.example.textboxresearch, PID: 15827
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:558)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.compose.ui.tooling.ComposableInvoker.invokeComposableMethod(ComposableInvoker.kt:163)
at androidx.compose.ui.tooling.ComposableInvoker.invokeComposable(ComposableInvoker.kt:203)
at androidx.compose.ui.tooling.PreviewActivity$setComposableContent$2.invoke(PreviewActivity.kt:77)
at androidx.compose.ui.tooling.PreviewActivity$setComposableContent$2.invoke(PreviewActivity.kt:76)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:428)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:177)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:123)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:114)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:157)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:156)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:156)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:140)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3314)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3304)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
2023-01-12 17:38:35.171 15827-15827 AndroidRuntime com.example.textboxresearch E at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3304)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3239)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:587)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:967)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1089)
at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131)
at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.kt:192)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131)
at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1176)
at android.view.View.dispatchAttachedToWindow(View.java:20753)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3490)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3497)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2613)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2126)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8658)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037)
at android.view.Choreographer.doCallbacks(Choreographer.java:845)
at android.view.Choreographer.doFrame(Choreographer.java:780)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
... 3 more
Caused by: java.lang.NoSuchFieldError: No static field $stable of type I in class Landroidx/compose/foundation/text/KeyboardActions; or its superclasses (declaration of 'androidx.compose.foundation.text.KeyboardActions' appears in /data/app/~~TC_W8Fki2PnCjomqRoVwJA==/com.example.textboxresearch-Ekc572auvJyczWtc91Ptug==/base.apk)
at androidx.compose.material.TextFieldKt.TextField(TextField.kt:207)
at com.example.textboxresearch.TestKt.CheckTest(Test.kt:29)
... 70 more
st...@google.com <st...@google.com> #123
You mean an OutlinedTextField? Can you share the snippet?
ja...@gmail.com <ja...@gmail.com> #124
kl...@google.com <kl...@google.com> #125
Can you please attach a video of BasicTextField
still going under the IME? And repro code if possible.
ja...@gmail.com <ja...@gmail.com> #126
kl...@google.com <kl...@google.com> #127
Ah, that's
wa...@gmail.com <wa...@gmail.com> #128
I am getting the same crash , waiting for next release , please release that fast
bl...@gmail.com <bl...@gmail.com> #129
Major fixes to this were just released in 1.4.0-alpha04
Major bugs were also released...
java.lang.NoSuchFieldError: No static field $stable of type I in class Landroidx/compose/foundation/text/KeyboardActions; or its superclasses (declaration of 'androidx.compose.foundation.text.KeyboardActions' appears in /data/app/~~xxx/base.apk)
at androidx.compose.material3.TextFieldKt$TextField$5.invoke(TextField.kt:343)
at androidx.compose.material3.TextFieldKt$TextField$5.invoke(TextField.kt:323)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228)
at androidx.compose.material3.TextFieldKt.TextField(TextField.kt:323)
st...@google.com <st...@google.com> #130
The crash above is reported here with workaround:
wa...@gmail.com <wa...@gmail.com> #131
so I upgraded to material 3 alpha04 and now I am not getting the Crash BUT I am still getting the text field going under the keyboard , I will post a video about it My TextField does take full width , is multiline but unless the user presses enter , it remains single lined , When I tap on the text field , the keyboard comes from underneath and stays on top of the field I don't use BringIntoViewRequester or any other code to bring it into view , I expect it to work magically.
ja...@gmail.com <ja...@gmail.com> #132
kl...@google.com <kl...@google.com> #133
Can you confirm you're also using Foundation version 1.4.0-alpha04? The bug was fixed in Foundation, not Material, and while material3 1.1.0-alpha04 should be using the latest alpha, I just want to make sure it actually is in your project. A video would be helpful, thanks.
ja...@gmail.com <ja...@gmail.com> #134
wa...@gmail.com <wa...@gmail.com> #135
I created a sample project and recorded this video , apparently the keyboard is opening and text field staying above when I tap on the field but not for long , when the text field becomes multiline , the text goes below keyboard
wa...@gmail.com <wa...@gmail.com> #136
This project using latest compose version
1.1.0-alpha04 for material 3
Compose version 1.4.0-alpha04 , UI , which should probably including foundation of the same version
kl...@google.com <kl...@google.com> #137
That's also
wa...@gmail.com <wa...@gmail.com> #138
So if I apply a fixed height , would it work ?
kl...@google.com <kl...@google.com> #139
Actually I think this might be a separate bug, since the resized field isn't internally scrollable. I filed
kl...@google.com <kl...@google.com> #140
We are closing this issue since the main case for this bug has been fixed: fixed-size text fields inside scrollable Column
s and LazyColumn
s will be kept above the keyboard when they gain focus and the keyboard becomes shown and would otherwise cover the field.
There are still some cases related to this that are still broken and being worked on, but those will be tracked in separate bugs going forward. The known remaining issues at this time are:
- Cursors in text fields that take all available space and are internally scrollable may disappear behind the keyboard (
)b/237190748 - Text fields that grow taller while being edited aren’t kept above the keyboard (
)b/266094055 - Crash with “No field $stable of type I in class Landroidx/compose/foundation/text/KeyboardActions” (
)b/265172081 - Text fields will stay below the keyboard when inside LazyVerticalGrid (
)b/265352893
Please follow those individual bugs for further updates.
If you find new issues, please
Description
If you put the Text Field Composable inside Lazy Column / Scrollable Column , Even After using the Insets / Content Padding on the Lazy Column / Scrollable Column
The Text goes below the keyboard Because Of The Scroll State
Since when the IME Opens the Ime comes above the Text And The Scroll State Would Remain the Same Lazy Column Wouldn't Scroll so the Text Would Remain Visible (Above Keyboard)