Repository: flutter
Issue: "setState() or markNeedsBuild() called during build" error combining DraggableScrollableSheet with FloatingActionButton
Labels: framework,a: error message,has reproducible steps,P2,team-framework,triaged-framework,found in release: 3.19,found in release: 3.22

### Steps to reproduce

I have a Scaffold with a `bottomNavigationBar` modifying a `_pageIndex` state variable. 
For `pageIndex == 1`:
- the Scaffold has a `bottomSheet` sheet set to a widget containing a `DraggableScrollableSheet`, with a button that when clicked, uses the `DraggableScrollableController.animateTo()` method to expand the bottom sheet.
- the Scaffold has a `floatingActionButton` set.

To reproduce (running in the iOS simulator):
- Select page 1 in the bottom nav bar
- Click the "Toggle" button in the bottom sheet, which should expand to 50%
- Select page 0 in the bottom nav bar

### Expected results

It switches back to Page 0, the bottom sheet and floating action button disappear, and there are no errors in the terminal.

### Actual results

Visually it works fine, but there is the following error in the debug console (which appear to be originating in the framework):
```
The following assertion was thrown while notifying listeners for TrainHoppingAnimation:
setState() or markNeedsBuild() called during build.
This RotationTransition widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: RotationTransition
    listenable: AnimationController#31171(⏭ 1.000; paused)➩CurveTween(curve: Cubic(0.42, 0.00, 1.00, 1.00))➩Tween<double>(0.875 → 1.0)➩1.0➩TrainHoppingAnimation(next: _AnimationSwap<double>(AnimationController#a27a8(⏭ 1.000; paused)➩Tween<double>(0.75 → 1.0)➩1.0, AnimationController#a27a8(⏭ 1.000; paused)➩CurveTween(curve: Threshold)➩1.0➪ReverseAnimation))
    state: _AnimatedState#bb51b
The widget which was currently being built when the offending call was made was: DraggableScrollableSheet
    dirty
    dependencies: [_InheritedResetNotifier, _InheritedTheme, _LocalizationsScope-[GlobalKey#46482]]
    state: _DraggableScrollableSheetState#00283

When the exception was thrown, this was the stack:
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5042:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5054:6)
#2      State.setState (package:flutter/src/widgets/framework.dart:1223:15)
#3      _AnimatedState._handleChange (package:flutter/src/widgets/transitions.dart:129:5)
#4      AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:161:19)
#5      TrainHoppingAnimation._valueChangeHandler (package:flutter/src/animation/animations.dart:582:7)
#6      AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:161:19)
#7      AnimationController.value= (package:flutter/src/animation/animation_controller.dart:395:5)
#8      ScaffoldState._floatingActionButtonVisibilityValue= (package:flutter/src/material/scaffold.dart:2532:47)
#9      _StandardBottomSheetState.extentChanged (package:flutter/src/material/scaffold.dart:3224:16)
#10     _NotificationElement.onNotification (package:flutter/src/widgets/notification_listener.dart:130:38)
#11     _NotificationNode.dispatchNotification (package:flutter/src/widgets/framework.dart:3320:18)
#12     _NotificationNode.dispatchNotification (package:flutter/src/widgets/framework.dart:3323:13)
#13     _NotificationNode.dispatchNotification (package:flutter/src/widgets/framework.dart:3323:13)
#14     _NotificationNode.dispatchNotification (package:flutter/src/widgets/framework.dart:3323:13)
#15     _NotificationNode.dispatchNotification (package:flutter/src/widgets/framework.dart:3323:13)
#16     Element.dispatchNotification (package:flutter/src/widgets/framework.dart:4942:24)
#17     Notification.dispatch (package:flutter/src/widgets/notification_listener.dart:60:13)
#18     _DraggableSheetExtent.updateSize (package:flutter/src/widgets/draggable_scrollable_sheet.dart:581:7)
#19     _DraggableScrollableSheetScrollController.reset (package:flutter/src/widgets/draggable_scrollable_sheet.dart:825:12)
#20     _DraggableScrollableSheetState.didChangeDependencies (package:flutter/src/widgets/draggable_scrollable_sheet.dart:680:25)
#21     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5640:13)
#22     Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#23     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2904:19)
#24     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:989:21)
#25     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:448:5)
#26     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
#27     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1311:9)
#28     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
#29     _invoke (dart:ui/hooks.dart:312:13)
#30     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5)
#31     _drawFrame (dart:ui/hooks.dart:283:31)

The TrainHoppingAnimation notifying listeners was: AnimationController#31171(⏭ 1.000; paused)➩CurveTween(curve: Cubic(0.42, 0.00, 1.00, 1.00))➩Tween<double>(0.875 → 1.0)➩1.0➩TrainHoppingAnimation(next: _AnimationSwap<double>(AnimationController#a27a8(⏭ 1.000; paused)➩Tween<double>(0.75 → 1.0)➩1.0, AnimationController#a27a8(⏭ 1.000; paused)➩CurveTween(curve: Threshold)➩1.0➪ReverseAnimation))
```

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _pageIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Page Index: ${this._pageIndex}',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
            ],
          ),
        ),
        bottomNavigationBar: NavigationBar(
          selectedIndex: _pageIndex,
          onDestinationSelected: (int index) {
            setState(() {
              _pageIndex = index;
            });
          },
          destinations: const [
            NavigationDestination(
              label: 'Page 0',
              icon: Icon(Icons.first_page),
            ),
            NavigationDestination(
              label: 'Page 1',
              icon: Icon(Icons.last_page),
            ),
          ],
        ),
        bottomSheet: _pageIndex == 1 ? MyBottomSheet() : null,
        floatingActionButton: _pageIndex == 1
            ? Builder(builder: (context) {
                return FloatingActionButton(
                    onPressed: () {
                      print('FAB shopping press');
                    },
                    child: const Icon(Icons.add));
              })
            : null);
  }
}

class MyBottomSheet extends StatefulWidget {
  const MyBottomSheet({super.key});

  @override
  State<StatefulWidget> createState() => _MyBottomSheetState();
}

class _MyBottomSheetState extends State<MyBottomSheet> {
  late DraggableScrollableController _controller;
  bool expanded = false;

  @override
  void initState() {
    super.initState();
    _controller = DraggableScrollableController();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(0.0),
        ),
      ),
      child: DraggableScrollableSheet(
        expand: false,
        snap: true,
        initialChildSize: 0.25,
        maxChildSize: 0.5,
        snapSizes: [0.5],
        controller: _controller,
        builder: (context, scrollController) {
          return Stack(
            children: [
              Container(
                padding: EdgeInsets.only(
                  top: 50.0,
                ),
                child: CustomScrollView(
                  slivers: [
                    SliverToBoxAdapter(
                      child: Column(
                        children: [
                          Text('Testing 123; expanded: ${expanded}',
                              style: Theme.of(context).textTheme.labelLarge),
                          TextButton(
                              onPressed: () {
                                print("Pressed...");
                                setState(() {
                                  if (!this.expanded) {
                                    this._controller.animateTo(0.5,
                                        duration: Durations.short4,
                                        curve: Curves.easeIn);
                                  }
                                  this.expanded = !expanded;
                                });
                              },
                              child: Text('Toggle'))
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              SingleChildScrollView(
                physics: const ClampingScrollPhysics(),
                controller: scrollController,
                child: Column(
                  children: [
                    SizedBox(
                      height: 12.0,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Container(
                          width: 30,
                          height: 5,
                          decoration: BoxDecoration(
                              color: Colors.grey[300],
                              borderRadius:
                                  BorderRadius.all(Radius.circular(12.0))),
                        ),
                      ],
                    ),
                    SizedBox(
                      height: 18.0,
                    ),
                  ],
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

```

</details>


### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

[Upload media here]

</details>


### Logs

<details open><summary>Logs</summary>

```console
[Paste your logs here]
```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[✓] Flutter (Channel stable, 3.19.5, on macOS 12.7.4 21H1123 darwin-x64, locale en-GB)
    • Flutter version 3.19.5 on channel stable at /Users/alex/Programming/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 300451adae (3 weeks ago), 2024-03-27 21:54:07 -0500
    • Engine revision e76c956498
    • Dart version 3.3.3
    • DevTools version 2.31.1

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).

[✓] VS Code (version 1.88.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.86.0

[✓] Connected device (3 available)
    • iPhone Xs (mobile) • B70C7918-2640-4093-A07A-13CA1DC8E970 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-16-2 (simulator)
    • macOS (desktop)    • macos                                • darwin-x64     • macOS 12.7.4 21H1123 darwin-x64
    • Chrome (web)       • chrome                               • web-javascript • Google Chrome 123.0.6312.123

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 2 categories.
```

</details>