Status Update
Comments
ma...@google.com <ma...@google.com>
sa...@gmail.com <sa...@gmail.com> #3
Low-hanging fruit. Shalom, mind taking a look during your work for PIs and loaders?
mo...@google.com <mo...@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.
va...@google.com <va...@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.
mo...@google.com <mo...@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]
ap...@google.com <ap...@google.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
Jetpack Compose version: 1.2.0-rc02
Jetpack Compose component(s) used: Foundation
Android Studio Build: #AI-221.4165.146.2211.8713749
Kotlin version: 1.6.21
When accessing the window insets via
asPaddingValues()
it does not account for the already consumed insets further in the hierarchy. E.g.The
PaddingValues
could be added to aLazyColumn
or similar layout that need extra padding, but only when a parent has not already consumed them. As far as I can tell it is not possible to access the amount of consumed insets, which makes it difficult to achieve this kind of layout.My feature request is either having
asPaddingValues
already account for the consumed insets (just likeModifier.navigationBarPadding()
) or at least provide read-only access to the amount of consumed insets.