google / accompanist

A collection of extension libraries for Jetpack Compose
https://google.github.io/accompanist
Apache License 2.0
7.43k stars 598 forks source link

[Navigation Material] Changing font size with bottom sheet opens crashes the app #1524

Closed Skeletonxf closed 1 year ago

Skeletonxf commented 1 year ago

Description

BottomSheetNavigator crashes when the font size is changed while a bottom sheet is open

Tested on v0.29.1-alpha and compose 1.4.0-beta02

Steps to reproduce

Adapted from the navigation material docs:

package com.example.composetest

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
import com.google.accompanist.navigation.material.bottomSheet
import com.google.accompanist.navigation.material.rememberBottomSheetNavigator

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApp()
        }
    }
}

// Adapted from docs example: https://google.github.io/accompanist/navigation-material/#bottom-sheet-destinations
@OptIn(ExperimentalMaterialNavigationApi::class)
@Composable
fun MyApp() {
    val bottomSheetNavigator = rememberBottomSheetNavigator()
    val navController = rememberNavController(bottomSheetNavigator)
    ModalBottomSheetLayout(bottomSheetNavigator) {
        NavHost(navController, "home") {
            composable(route = "home") {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center
                ) {
                    Column {
                        Text(text = "This is the main content")
                        Button(
                            onClick = { navController.navigate("sheet") }
                        ) {
                            Text(text = "Show sheet")
                        }
                    }
                }
            }
            bottomSheet(route = "sheet") {
                Text("This is a cool bottom sheet!")
            }
        }
    }
}

Steps:

Open app, Press button to open bottom sheet Change font size in settings Return to app App crashes

Expected behaviour

Font size changes and bottom sheet remains open

Additional context

The crash seems to occur because of sheetContent = bottomSheetNavigator.sheetContent in the accompanist ModalBottomSheetLayout wrapper of the material ModalBottomSheetLayout. If I replace all the accompanist dependencies and use the material ModalBottomSheetLayout directly (ie with sheetContent = { }) no crash happens. However, if I manually create and remember the accompanist bottom sheet navigator and sheet state so I can call the bottom sheet navigator sheetContent method myself in the material ModalBottomSheetLayout sheetContent the crash returns.

jossiwolf commented 1 year ago

Hi, do you have the stack trace?

Skeletonxf commented 1 year ago
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.composetest, PID: 22455
    java.lang.IllegalStateException: The offset was read before being initialized. Did you access the offset in a phase before layout, like effects or composition?
        at androidx.compose.material.SwipeableV2State.requireOffset(SwipeableV2.kt:208)
        at androidx.compose.material.ModalBottomSheetKt$ModalBottomSheetLayout$1$3.invoke-Bjo55l4(ModalBottomSheet.kt:485)
        at androidx.compose.material.ModalBottomSheetKt$ModalBottomSheetLayout$1$3.invoke(ModalBottomSheet.kt:481)
        at androidx.compose.foundation.layout.OffsetPxModifier$measure$1.invoke(Offset.kt:202)
        at androidx.compose.foundation.layout.OffsetPxModifier$measure$1.invoke(Offset.kt:201)
        at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.node.LayoutModifierNodeCoordinator.placeAt-f8xVGno(LayoutModifierNodeCoordinator.kt:202)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:434)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:199)
        at androidx.compose.foundation.layout.FillModifier$measure$1.invoke(Size.kt:663)
        at androidx.compose.foundation.layout.FillModifier$measure$1.invoke(Size.kt:662)
        at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.node.LayoutModifierNodeCoordinator.placeAt-f8xVGno(LayoutModifierNodeCoordinator.kt:202)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:434)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:199)
        at androidx.compose.foundation.layout.SizeModifier$measure$1.invoke(Size.kt:783)
        at androidx.compose.foundation.layout.SizeModifier$measure$1.invoke(Size.kt:782)
        at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.node.LayoutModifierNodeCoordinator.placeAt-f8xVGno(LayoutModifierNodeCoordinator.kt:202)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:445)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:451)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutModifierSnapshotReads$ui_release(OwnerSnapshotObserver.kt:92)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeOuterCoordinator-f8xVGno(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeAt-f8xVGno(LayoutNodeLayoutDelegate.kt:428)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:445)
        at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50$default(Placeable.kt:223)
E/AndroidRuntime:     at androidx.compose.foundation.layout.BoxKt.placeInBox(Box.kt:186)
        at androidx.compose.foundation.layout.BoxKt.access$placeInBox(Box.kt:1)
        at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1$measure$5.invoke(Box.kt:167)
        at androidx.compose.foundation.layout.BoxKt$boxMeasurePolicy$1$measure$5.invoke(Box.kt:163)
        at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1.placeChildren(SubcomposeLayout.kt:610)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:276)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:268)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:77)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.layoutChildren(LayoutNodeLayoutDelegate.kt:268)
        at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:941)
        at androidx.compose.ui.node.InnerNodeCoordinator.placeAt-f8xVGno(InnerNodeCoordinator.kt:137)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeWithLayer-aW-9-wM(Placeable.kt:471)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:453)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutModifierSnapshotReads$ui_release(OwnerSnapshotObserver.kt:92)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeOuterCoordinator-f8xVGno(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeAt-f8xVGno(LayoutNodeLayoutDelegate.kt:428)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelativeWithLayer(Placeable.kt:460)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelativeWithLayer$default(Placeable.kt:266)
        at androidx.compose.ui.layout.RootMeasurePolicy$measure$2.invoke(RootMeasurePolicy.kt:43)
        at androidx.compose.ui.layout.RootMeasurePolicy$measure$2.invoke(RootMeasurePolicy.kt:39)
E/AndroidRuntime:     at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:276)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:268)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:77)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.layoutChildren(LayoutNodeLayoutDelegate.kt:268)
        at androidx.compose.ui.node.LayoutNode.onNodePlaced$ui_release(LayoutNode.kt:941)
        at androidx.compose.ui.node.InnerNodeCoordinator.placeAt-f8xVGno(InnerNodeCoordinator.kt:137)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.place-70tqf50(Placeable.kt:445)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:451)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$placeOuterCoordinator$1.invoke(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2200)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:234)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke(SnapshotStateObserver.kt:230)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:120)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutModifierSnapshotReads$ui_release(OwnerSnapshotObserver.kt:92)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeOuterCoordinator-f8xVGno(LayoutNodeLayoutDelegate.kt:445)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.placeAt-f8xVGno(LayoutNodeLayoutDelegate.kt:428)
        at androidx.compose.ui.layout.Placeable.access$placeAt-f8xVGno(Placeable.kt:35)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative(Placeable.kt:434)
        at androidx.compose.ui.layout.Placeable$PlacementScope.placeRelative$default(Placeable.kt:199)
        at androidx.compose.ui.node.LayoutNode.place$ui_release(LayoutNode.kt:813)
        at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:443)
        at androidx.compose.ui.node.MeasureAndLayoutDelegate.access$remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:39)
        at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:330)
        at androidx.compose.ui.platform.AndroidComposeView.onLayout(AndroidComposeView.android.kt:878)
        at android.view.View.layout(View.java:23143)
        at android.view.ViewGroup.layout(ViewGroup.java:6412)
E/AndroidRuntime:     at androidx.compose.ui.platform.AbstractComposeView.internalOnLayout$ui_release(ComposeView.android.kt:322)
        at androidx.compose.ui.platform.AbstractComposeView.onLayout(ComposeView.android.kt:313)
        at android.view.View.layout(View.java:23143)
        at android.view.ViewGroup.layout(ViewGroup.java:6412)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:23143)
        at android.view.ViewGroup.layout(ViewGroup.java:6412)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:23143)
        at android.view.ViewGroup.layout(ViewGroup.java:6412)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:798)
        at android.view.View.layout(View.java:23143)
        at android.view.ViewGroup.layout(ViewGroup.java:6412)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3684)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3143)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2126)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8653)
        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)
        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)
jossiwolf commented 1 year ago

Thanks! This is the same root cause as #1493. We're fixing this upstream. Please follow along in #1493 for updates.