Status Update
Comments
jo...@google.com <jo...@google.com> #2
Hello, we're also affected by the same issue.
It seems like this issue has been introduced by Compose Version 1.6.0+, as it didn't occur on our App version which contained Compose version 1.5.4. However, after we updated Compose to 1.6.0+ (specifically 1.6.2) it occured for more than 100 users.
Fatal Exception: java.lang.IllegalStateException: SelectionLayout must not be empty.
at androidx.compose.foundation.text.selection.SelectionLayoutBuilder.build(SelectionLayout.kt:449)
at androidx.compose.foundation.text.selection.SelectionManager.getSelectionLayout-Wko1d7g(SelectionManager.kt:796)
at androidx.compose.foundation.text.selection.SelectionManager.updateSelection-jyLRC_s$foundation_release(SelectionManager.kt:753)
at androidx.compose.foundation.text.selection.SelectionManager.updateSelection-qNKwrvQ$foundation_release(SelectionManager.kt:716)
at androidx.compose.foundation.text.selection.SelectionManager$4.invoke-pGV3PM0(SelectionManager.kt:291)
at androidx.compose.foundation.text.selection.SelectionManager$4.invoke(SelectionManager.kt:278)
at androidx.compose.foundation.text.selection.SelectionRegistrarImpl.notifySelectionUpdate-njBpvok(SelectionRegistrarImpl.kt:209)
at androidx.compose.foundation.text.modifiers.SelectionControllerKt$makeSelectionModifier$longPressDragObserver$1.onDrag-k-4lQ0M(SelectionController.kt:217)
at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$2.invoke(SelectionGestures.kt:124)
at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$2.invoke(SelectionGestures.kt:123)
at androidx.compose.foundation.gestures.DragGestureDetectorKt.drag-jO51t88(DragGestureDetector.kt:114)
at androidx.compose.foundation.gestures.DragGestureDetectorKt$drag$1.invokeSuspend(DragGestureDetector.kt:1)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:665)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent(SuspendingPointerInputFilter.kt:544)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:566)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:317)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:185)
at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:104)
at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:113)
at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1576)
at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1527)
at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:1466)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3211)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2883)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:531)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1896)
at android.app.Activity.dispatchTouchEvent(Activity.java:4216)
at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:489)
at android.view.View.dispatchPointerEvent(View.java:14812)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6591)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6392)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5813)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5870)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5836)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5844)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5817)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5870)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5836)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6018)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5844)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6075)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5817)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5870)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5836)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5844)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5817)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8894)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8843)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8811)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9045)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:260)
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loopOnce(Looper.java:161)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:8005)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1039)
je...@google.com <je...@google.com> #3
Can you provide any information on how your SelectionContainer
s are set up? What is between your SelectionContainer
s and the Text
/BasicText
s in your hierarchy?
ap...@google.com <ap...@google.com> #4
In the past I had the issue that it crashed when the XML layout collapsed (resulting in a height of 0) while text was selected in the composable. Maybe there is a regression regarding this edge case on some devices?
pr...@google.com <pr...@google.com> #5
TextField
or Text
? TextField
s don't have any interaction with SelectionContainer
s, they handle selection themselves. The stack trace indicate Text
or BasicText
being used.
Is it a single Text
within the container? or multiple?
Any other information you can provide on the layout changing? Can it happen during a selection gesture? The stack trace implies that the crash happens during the drag part of a long-press drag directly on the text (not on a handle), not the initial long-press (could be the frame right after the initial long-press though if it moves even a pixel), so I'm curious if there is any layout changing during the gesture.
Is the text scrollable?
Thanks for the information!
Description
When the down and the up event arrive in rapid succession, it is possible that the onPress callback is executed after the onTap callback.
It is currently not possible to reproduce this in a test, because we use an
UnconfinedTestDispatcher
. When we switch to aStandardTestDispatcher
, the following test (when added toTapGestureDetectorTest.kt
) will fail:While very difficult, I think you could reproduce it in a demo app with an incredibly short tap.