Skip to content

DraggableScrollableSheet.snap throws for multiple ScrollPositions attached #105469

@Piinks

Description

@Piinks

Internal bug: b/234838047

Steps to Reproduce

  1. Execute flutter run on the code sample
  2. Tap on button

Expected results:

The views animate from one to the other.

Actual results:

An assertion is thrown.

ScrollController attached to multiple scroll views.

This is because during the animation, the DraggableScrollableSheet tries to access the ScrollPosition through the ScrollController - but more than one position is attached. This appears to be caused by a post frame callback that is triggered by snap being true.

WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {

It may be that there is a condition we are not accounting for when initiating the snap.

Code sample
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(title: 'Draggable Bug'),
    );
  }
}

class View1 extends StatelessWidget {
  View1({required this.next});
  final void Function() next;

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: next,
          child: Text('switch to View2'),
        ),
        Container(
          height: 400,
          color: Colors.blue,
        ),
      ],
    );
  }
}

class View2 extends StatelessWidget {
  View2({required this.next});
  final void Function() next;
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: next,
          child: Text('switch to View1'),
        ),
        Container(
          height: 400,
          color: Colors.red,
        ),
      ],
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var s = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: DraggableScrollableSheet(
            initialChildSize: 0.25,
            minChildSize: 0.25,
            snap: true,
            snapSizes: const [0.25, 0.5, 1.0],
            builder: (context, scrollController) {
              return PrimaryScrollController(
                controller: scrollController,
                child: AnimatedSwitcher(
                  duration: const Duration(milliseconds: 500),
                  child: (s % 2 == 0)
                      ? View1(
                          next: () {
                            setState(() {
                              ++s;
                            });
                          },
                        )
                      : View2(
                          next: () {
                            setState(() {
                              ++s;
                            });
                          },
                        ),
                ),
              );
            },
          ),
    );
  }
}
Logs
[✓] Flutter (Channel master, 3.1.0-0.0.pre.1119, on macOS 12.4 21F79 darwin-x64, locale en)
    • Flutter version 3.1.0-0.0.pre.1119 at /Users/katelovett/_github/flutter
    • Upstream repository [email protected]:flutter/flutter.git
    • Framework revision 1b2ee411aa (6 hours ago), 2022-06-06 07:55:09 -0700
    • Engine revision 4e42059e16
    • Dart version 2.18.0 (build 2.18.0-170.0.dev)
    • DevTools version 2.14.0

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0-rc2)
    • Android SDK at /Users/katelovett/Library/Android/sdk
    • Platform android-31, build-tools 31.0.0-rc2
    • Java binary at: /Applications/Android Studio with
      Blaze.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio
    • Android Studio at /Applications/Android Studio with Blaze Beta.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] Android Studio (version 2020.3)
    • Android Studio at /Applications/Android Studio with Blaze.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)

[✓] IntelliJ IDEA Ultimate Edition (version 2021.3.3)
    • IntelliJ at /Applications/IntelliJ UE (stable).app
    • Flutter plugin version 66.0.3
    • Dart plugin version 213.7371

[✓] VS Code (version 1.67.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.42.0

[✓] Connected device (4 available)
    • Piinks Pro (mobile)                 • 00008110-000444E03C2A801E            • ios
      • iOS 15.5 19F77
    • iPhone SE (3rd generation) (mobile) • 4E826BB1-B283-403A-8E94-8574FD7DA7D2 • ios
      • com.apple.CoreSimulator.SimRuntime.iOS-15-4 (simulator)
    • macOS (desktop)                     • macos                                • darwin-x64
      • macOS 12.4 21F79 darwin-x64
    • Chrome (web)                        • chrome                               • web-javascript
      • Google Chrome 102.0.5005.61
    ! Error: Piinks Pro is busy: Fetching debug symbols for Piinks Pro. Xcode will continue when
      Piinks Pro is finished. (code -10)

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

I am not sure what the expected behavior is here regarding snap in this case where more than one position is attached

  • should all positions snap?
  • should none?
  • should we throw a more informative error message, and if so how should the user resolve this?

This snap logic was added in #90354 by @caseycrogers
@dnfield and @xu-baolin may also know what the expected behavior here is.

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: error messageError messages from the Flutter frameworkc: fatal crashCrashes that terminate the processcustomer: googleVarious Google teamsf: scrollingViewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions