Status Update
Comments
ma...@google.com <ma...@google.com>
ap...@google.com <ap...@google.com> #3
Low-hanging fruit. Shalom, mind taking a look during your work for PIs and loaders?
ap...@google.com <ap...@google.com> #4
We can check for NaN
, but what is the expected behavior here if a NaN
is passed in?
- We can throw an exception, but that would end in the same result you are experiencing now (i.e. a crash if you don't handle it)
- We can just set the progress to zero in cases of
NaN
s, but then you would not be able to tell that you have a problem in your implementation and you are passing in illegal values. - We can document it that we only expect a non
NaN
values, but that seems a bit redundant and we don't usually adding these to the docs as it's implicit in most cases.
ap...@google.com <ap...@google.com> #5
On my end, I discovered it was caused by division by zero and just set the bar to indeterminate in that case.
ma...@google.com <ma...@google.com>
pr...@google.com <pr...@google.com> #6
I also experience this crash in our released app, I can reproduce this with both Material2 and Material3 with latest stable and alpha-versions, but only with enabled Talkback-service.
Since this crash only happens with enabled Talkback-service and the app works fine otherwise, I consider this to be a bug in the interaction between Talkback and the participating Material-compose frameworks.
build.gradle:
implementation "androidx.compose.material:material:1.8.0-alpha08"
implementation "androidx.compose.material3:material3:1.4.0-alpha06"
Minimal reproducible examples:
@Preview
@Composable
private fun MinimalReproducibleExampleM2Preview() {
androidx.compose.material.LinearProgressIndicator(
modifier =
Modifier
.fillMaxWidth()
.height(12.dp),
progress = 0f / 0f,
)
}
@Preview
@Composable
private fun MinimalReproducibleExampleM3Preview() {
androidx.compose.material3.LinearProgressIndicator(
modifier =
Modifier
.fillMaxWidth()
.height(12.dp),
progress = { 0f / 0f },
)
}
Crash in Material2:
FATAL EXCEPTION: main (Ask Gemini)
Process: de.billiger.android, PID: 416
java.lang.IllegalArgumentException: current must not be NaN
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:662)
at androidx.compose.foundation.ProgressSemanticsKt$progressSemantics$1.invoke(ProgressSemantics.kt:53)
at androidx.compose.foundation.ProgressSemanticsKt$progressSemantics$1.invoke(ProgressSemantics.kt:51)
at androidx.compose.ui.semantics.CoreSemanticsModifierNode.applySemantics(SemanticsModifier.kt:59)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:442)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:433)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2496)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:460)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:244)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeSemanticsReads$ui_release(OwnerSnapshotObserver.kt:121)
at androidx.compose.ui.node.LayoutNode.getCollapsedSemantics$ui_release(LayoutNode.kt:433)
at androidx.compose.ui.semantics.SemanticsNodeKt.SemanticsNode(SemanticsNode.kt:49)
at androidx.compose.ui.semantics.SemanticsNode.fillOneLayerOfSemanticsWrappers(SemanticsNode.kt:278)
at androidx.compose.ui.semantics.SemanticsNode.unmergedChildren$ui_release(SemanticsNode.kt:257)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release(SemanticsNode.kt:338)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release$default(SemanticsNode.kt:322)
at androidx.compose.ui.semantics.SemanticsNode.getReplacedChildren$ui_release(SemanticsNode.kt:305)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap$findAllSemanticNodesRecursive(SemanticsUtils.android.kt:195)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap(SemanticsUtils.android.kt:230)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.getCurrentSemanticsNodes(AndroidComposeViewAccessibilityDelegateCompat.android.kt:311)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.createEvent(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1577)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1519)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView$default(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1509)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendSubtreeChangeAccessibilityEvents(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2377)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.boundsUpdatesEventLoop$ui_release(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2251)
at androidx.compose.ui.platform.AndroidComposeView.boundsUpdatesAccessibilityEventLoop(AndroidComposeView.android.kt:1639)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$1$1.invokeSuspend(Wrapper.android.kt:148)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309) (Ask Gemini)
at android.view.Choreographer.doCallbacks(Choreographer.java:923)
at android.view.Choreographer.doFrame(Choreographer.java:847)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@93d2fd8, androidx.compose.runtime.BroadcastFrameClock@cb15f31, StandaloneCoroutine{Cancelling}@36ca616, AndroidUiDispatcher@ae19b97]
Crash in Material3:
FATAL EXCEPTION: main (Ask Gemini)
Process: de.billiger.android, PID: 4219
java.lang.IllegalArgumentException: current must not be NaN
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:662)
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:655)
at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$3$1.invoke(ProgressIndicator.kt:156)
at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$3$1.invoke(ProgressIndicator.kt:155)
at androidx.compose.ui.semantics.CoreSemanticsModifierNode.applySemantics(SemanticsModifier.kt:59)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:442)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:433)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2496)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:460)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:244)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeSemanticsReads$ui_release(OwnerSnapshotObserver.kt:121)
at androidx.compose.ui.node.LayoutNode.getCollapsedSemantics$ui_release(LayoutNode.kt:433)
at androidx.compose.ui.semantics.SemanticsNodeKt.SemanticsNode(SemanticsNode.kt:49)
at androidx.compose.ui.semantics.SemanticsNode.fillOneLayerOfSemanticsWrappers(SemanticsNode.kt:278)
at androidx.compose.ui.semantics.SemanticsNode.unmergedChildren$ui_release(SemanticsNode.kt:257)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release(SemanticsNode.kt:338)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release$default(SemanticsNode.kt:322)
at androidx.compose.ui.semantics.SemanticsNode.getReplacedChildren$ui_release(SemanticsNode.kt:305)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap$findAllSemanticNodesRecursive(SemanticsUtils.android.kt:195)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap(SemanticsUtils.android.kt:230)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.getCurrentSemanticsNodes(AndroidComposeViewAccessibilityDelegateCompat.android.kt:311)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.createEvent(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1577)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1519)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView$default(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1509)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendSubtreeChangeAccessibilityEvents(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2377)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.boundsUpdatesEventLoop$ui_release(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2251)
at androidx.compose.ui.platform.AndroidComposeView.boundsUpdatesAccessibilityEventLoop(AndroidComposeView.android.kt:1639)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$1$1.invokeSuspend(Wrapper.android.kt:148)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68) (Ask Gemini)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
at android.view.Choreographer.doCallbacks(Choreographer.java:923)
at android.view.Choreographer.doFrame(Choreographer.java:847)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@f9ecebb, androidx.compose.runtime.BroadcastFrameClock@93d2fd8, StandaloneCoroutine{Cancelling}@cb15f31, AndroidUiDispatcher@36ca616]
xe...@gmail.com <xe...@gmail.com> #7
Project: platform/frameworks/support
Branch: androidx-main
Author: Shalom Gibly <
Link:
Prevent a crash when Float.NaN is a progress value
Expand for full commit details
Prevent a crash when Float.NaN is a progress value
- Check for a NaN value and return zero if a progress lambda is
producing it and passing it into a `ProgressBarRangeInfo`. The range
info will throw an exception if a NaN is passed in.
- Applied the check at the progress indicators (M3 & M2), and at the
loading indicator.
- The remaining implementation does not cras on NaN, but the UI usually
does not render anything.
- Also, switched to use `fastCoerceIn` instead of `coerceIn`.
Test: Added
Fixes: 352364576
Relnote: "Fixed a crash at the progress and loading indicators in case a
Float.NaN is passed in as a progress."
Change-Id: I4fa969a1d46358a6f1db8b28cb0a375a809102c2
Files:
- M
compose/material/material/src/commonMain/kotlin/androidx/compose/material/ProgressIndicator.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorTest.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ProgressIndicatorTest.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/LoadingIndicator.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ProgressIndicator.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
Hash: bf90726d0c7fadd916c5c8bf38b18f6a9a5d7a6b
Date: Wed Jan 22 16:28:41 2025
Description
The current implementation uses the same component for the unexpanded search bar and the expanded search view. This makes it hard to use the search bar in the middle of other content, since you have to ensure not to accidentally pass constraints that prevent it from being full screen.
Making the full-screen search view into a dialog would avoid most of these issues.
If there is enough interest (by +1-ing this issue), we could explore the possibility of using this approach.