Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom ScrollPhysics breaks NestedScrollView #34316

Open
maks opened this issue Jun 12, 2019 · 4 comments
Open

Custom ScrollPhysics breaks NestedScrollView #34316

maks opened this issue Jun 12, 2019 · 4 comments
Labels
a: animation Animation APIs f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-design Owned by Design Languages team triaged-design Triaged by Design Languages team

Comments

@maks
Copy link

maks commented Jun 12, 2019

Steps to Reproduce

I have a small app here: https://github.com/maks/flutter-space
that demonstrates the issue.

Its basically just the example code from the NestedScrollView documentation but using a custom Physics class that just uses the ScrollSpringSimulation to try to force the AppBar to always snap back to the fully expanded position.

What I expect to happen:

is that the Appbar always snaps back to the fully expanded position, using:

ScrollSpringSimulation(spring, position.pixels, target, 0,
        tolerance: tolerance);

What actually happens:

When the user fling is low velocity or scroll gesture is slow, the Appbar behaves as expected.
BUT if there is a fast enough fling or rapid scroll gesture, it stops the processing of the physics simulation for some reason, making the Appbar "stuck" in a partially expanded state. Touching anywhere causes the simulation to be run again and then it correctly scrolls back to the fully expanded position.

I've observed this on Android and iOS, and explicitly set the physics for the "inner" CustomScrollView to ClampingScrollPhysics just to demonstrate the issue more easily on iOS without running into other issues such as #33367, though that issue may be somewhat related to this one.

sliverappbar-scroll-physics-issue

Logs

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.5.4-hotfix.2, on Linux, locale en_AU.UTF-8)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Android Studio (version 3.4)
[✓] Android Studio (version 3.3)
[✓] VS Code (version 1.35.0)
[✓] Connected device (1 available)

• No issues found!
@LongCatIsLooong LongCatIsLooong added f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. labels Jun 12, 2019
@peng8350
Copy link

same issue.I want to do Refresh under SliverAppBar with NestedScrollView,though I add this line in applyUserOffset method can make me work.

 else if (delta < 0.0&&_innerController.position.extentBefore!=0.0) {

but if body has multiple positions,it will crash

@VladyslavBondarenko VladyslavBondarenko added found in release: 1.18 Occurs in 1.18 has reproducible steps The issue has been confirmed reproducible and is ready to work on labels Apr 22, 2020
@TahaTesser
Copy link
Member

code sample
import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Space',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  ScrollController _scrollController;

  final List<String> _tabs = ["Earth", "Mars", "Venus"];

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _scrollController.addListener(() {
      print(
          "${_scrollController.offset} | ${_scrollController.position.maxScrollExtent}");
    });
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: DefaultTabController(
        length: _tabs.length, // This is the number of tabs.
        child: NestedScrollView(
          physics: SnapToEndsPhysics(),
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            // These are the slivers that show up in the "outer" scroll view.
            return <Widget>[
              SliverOverlapAbsorber(
                // This widget takes the overlapping behavior of the SliverAppBar,
                // and redirects it to the SliverOverlapInjector below. If it is
                // missing, then it is possible for the nested "inner" scroll view
                // below to end up under the SliverAppBar even when the inner
                // scroll view thinks it has not been scrolled.
                // This is not necessary if the "headerSliverBuilder" only builds
                // widgets that do not overlap the next sliver.
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                  title: const Text(
                      'Planets'), // This is the title in the app bar.
                  pinned: true,
                  expandedHeight: 350.0,
                  // The "forceElevated" property causes the SliverAppBar to show
                  // a shadow. The "innerBoxIsScrolled" parameter is true when the
                  // inner scroll view is scrolled beyond its "zero" point, i.e.
                  // when it appears to be scrolled below the SliverAppBar.
                  // Without this, there are cases where the shadow would appear
                  // or not appear inappropriately, because the SliverAppBar is
                  // not actually aware of the precise position of the inner
                  // scroll views.
                  forceElevated: innerBoxIsScrolled,
                  bottom: TabBar(
                    // These are the widgets to put in each tab in the tab bar.
                    tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            // These are the contents of the tab views, below the tabs.
            children: _tabs.map((String name) {
              return SafeArea(
                top: false,
                bottom: false,
                child: Builder(
                  // This Builder is needed to provide a BuildContext that is "inside"
                  // the NestedScrollView, so that sliverOverlapAbsorberHandleFor() can
                  // find the NestedScrollView.
                  builder: (BuildContext context) {
                    return CustomScrollView(
                      // The "controller" and "primary" members should be left
                      // unset, so that the NestedScrollView can control this
                      // inner scroll view.
                      // If the "controller" property is set, then this scroll
                      // view will not be associated with the NestedScrollView.
                      // The PageStorageKey should be unique to this ScrollView;
                      // it allows the list to remember its scroll position when
                      // the tab view is not on the screen.
                      key: PageStorageKey<String>(name),
                      physics:
                          ClampingScrollPhysics(), //set this explcitly to Androids to make issue more obvious on iOS
                      slivers: <Widget>[
                        SliverOverlapInjector(
                          // This is the flip side of the SliverOverlapAbsorber above.
                          handle:
                              NestedScrollView.sliverOverlapAbsorberHandleFor(
                                  context),
                        ),
                        SliverPadding(
                          padding: const EdgeInsets.all(8.0),
                          // In this example, the inner scroll view has
                          // fixed-height list items, hence the use of
                          // SliverFixedExtentList. However, one could use any
                          // sliver widget here, e.g. SliverList or SliverGrid.
                          sliver: SliverFixedExtentList(
                            // The items in this example are fixed to 48 pixels
                            // high. This matches the Material Design spec for
                            // ListTile widgets.
                            itemExtent: 48.0,
                            delegate: SliverChildBuilderDelegate(
                              (BuildContext context, int index) {
                                // This builder is called for each child.
                                // In this example, we just number each list item.
                                return ListTile(
                                  title: Text('$name $index'),
                                );
                              },
                              // The childCount of the SliverChildBuilderDelegate
                              // specifies how many children this inner list
                              // has. In this example, each tab has a list of
                              // exactly 30 items, but this is arbitrary.
                              childCount: 30,
                            ),
                          ),
                        ),
                      ],
                    );
                  },
                ),
              );
            }).toList(),
          ),
        ),
      )),
    );
  }
}

/// A snapping physics that always lands  at the  bottom of the scrollable only
class SnapToEndsPhysics extends ScrollPhysics {
  /// Creates a scroll physics that always lands on top or bottom of scrollable.
  const SnapToEndsPhysics({ScrollPhysics parent}) : super(parent: parent);

  @override
  ScrollPhysics applyTo(ScrollPhysics ancestor) {
    return SnapToEndsPhysics(parent: buildParent(ancestor));
  }

  @override
  Simulation createBallisticSimulation(
      ScrollMetrics position, double velocity) {
    print("vel: $velocity pos: $position");

    final target = 0.0;
    var sim = ScrollSpringSimulation(spring, position.pixels, target, 0,
        tolerance: tolerance);
    return sim;
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.22.5 at /Users/tahatesser/Code/flutter_stable
    • Framework revision 7891006299 (3 weeks ago), 2020-12-10 11:54:40 -0800
    • Engine revision ae90085a84
    • Dart version 2.10.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/sdk
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    • CocoaPods version 1.10.0

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

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

[✓] Connected device (2 available)
    • Taha’s iPad (mobile) • 00008020-000255113EE8402E            • ios • iOS 14.3
    • iPhone 12 (mobile)   • 12D8FF8E-2815-436E-9951-B8A6A42E4ACF • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)

! Doctor found issues in 1 category.
[✓] Flutter (Channel master, 1.26.0-2.0.pre.145, on macOS 11.1 20C69 darwin-x64, locale en-GB)
    • Flutter version 1.26.0-2.0.pre.145 at /Users/tahatesser/Code/flutter_master
    • Framework revision 38fe7e2b1c (9 hours ago), 2020-12-28 21:39:03 -0500
    • Engine revision 892034dc6a
    • Dart version 2.12.0 (build 2.12.0-179.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Volumes/Extreme/sdk
    • Platform android-30, build-tools 30.0.3
    • ANDROID_HOME = /Volumes/Extreme/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Volumes/Extreme/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    • CocoaPods version 1.10.0

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

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.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 1.8.0_242-release-1644-b3-6915495)

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

[✓] Connected device (4 available)
    • Taha’s iPad (mobile) • 00008020-000255113EE8402E            • ios            • iOS 14.3
    • iPhone 12 (mobile)   • 12D8FF8E-2815-436E-9951-B8A6A42E4ACF • ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)      • macos                                • darwin-x64     • macOS 11.1 20C69 darwin-x64
    • Chrome (web)         • chrome                               • web-javascript • Google Chrome 87.0.4280.88

• No issues found!

@TahaTesser TahaTesser added a: animation Animation APIs f: material design flutter/packages/flutter/material repository. found in release: 1.22 Found to occur in 1.22 found in release: 1.26 Found to occur in 1.26 and removed found in release: 1.18 Occurs in 1.18 labels Dec 29, 2020
@habibshaban
Copy link

Steps to Reproduce

I have a small app here: https://github.com/maks/flutter-space
that demonstrates the issue.

Its basically just the example code from the NestedScrollView documentation but using a custom Physics class that just uses the ScrollSpringSimulation to try to force the AppBar to always snap back to the fully expanded position.

What I expect to happen:

is that the Appbar always snaps back to the fully expanded position, using:

ScrollSpringSimulation(spring, position.pixels, target, 0,
        tolerance: tolerance);

What actually happens:

When the user fling is low velocity or scroll gesture is slow, the Appbar behaves as expected.
BUT if there is a fast enough fling or rapid scroll gesture, it stops the processing of the physics simulation for some reason, making the Appbar "stuck" in a partially expanded state. Touching anywhere causes the simulation to be run again and then it correctly scrolls back to the fully expanded position.

I've observed this on Android and iOS, and explicitly set the physics for the "inner" CustomScrollView to ClampingScrollPhysics just to demonstrate the issue more easily on iOS without running into other issues such as #33367, though that issue may be somewhat related to this one.

sliverappbar-scroll-physics-issue

Logs

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.5.4-hotfix.2, on Linux, locale en_AU.UTF-8)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Android Studio (version 3.4)
[✓] Android Studio (version 3.3)
[✓] VS Code (version 1.35.0)
[✓] Connected device (1 available)

• No issues found!

Same issue for me and relative to other issues
if any one have the solution tell us

@maheshmnj
Copy link
Member

Reproduces on stable 3.3 and master 3.7, Spring simulation doesn't work.

Screen.Recording.2022-12-14.at.8.05.47.PM.mov
flutter doctor -v (mac)
[✓] Flutter (Channel master, 3.7.0-3.0.pre.33, on macOS 12.6 21G115 darwin-arm64, locale en-IN)
    • Flutter version 3.7.0-3.0.pre.33 on channel master 
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 5201856805 (38 minutes ago), 2022-12-05 18:27:21 -0800
    • Engine revision a309d239c4
    • Dart version 2.19.0 (build 2.19.0-463.0.dev)
    • DevTools version 2.20.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly
      to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc4)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0-rc4
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

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

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.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.12+0-b1504.28-7817840)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

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

[✓] Connected device (3 available)
    • iPhone 12 Pro (mobile) • 026D5789-9E78-4AD5-B1B2-3F8D4E7F65E4 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.6 21G115 darwin-arm64
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 108.0.5359.94

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

• No issues found!
[✓] Flutter (Channel stable, 3.3.9, on macOS 12.6 21G115 darwin-arm, locale en-IN)
    • Flutter version 3.3.9 on channel stable at /Users/mahesh/Development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (24 hours ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc4)
    • Android SDK at /Users/mahesh/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0-rc4
    • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

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

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.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.12+0-b1504.28-7817840)

[✓] IntelliJ IDEA Community Edition (version 2021.2.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5080.8

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

[✓] Connected device (3 available)
    • iPhone 12 Pro (mobile) • 026D5789-9E78-4AD5-B1B2-3F8D4E7F65E4 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • macOS (desktop)        • macos                                • darwin-arm64   • macOS 12.6 21G115 darwin-arm
    • Chrome (web)           • chrome                               • web-javascript • Google Chrome 107.0.5304.110

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

• No issues found!

@maheshmnj maheshmnj added found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 and removed found in release: 1.22 Found to occur in 1.22 found in release: 1.26 Found to occur in 1.26 labels Dec 15, 2022
@Piinks Piinks added the P2 Important issues not at the top of the work list label Mar 21, 2023
@Piinks Piinks changed the title SliverAppBar with NestScrollview does not correctly scroll when physics set Custom ScrollPhysics breaks NestScrollview May 30, 2023
@Piinks Piinks changed the title Custom ScrollPhysics breaks NestScrollview Custom ScrollPhysics breaks NestedScrollView May 30, 2023
@flutter-triage-bot flutter-triage-bot bot added multiteam-retriage-candidate team-design Owned by Design Languages team triaged-design Triaged by Design Languages team labels Jul 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: animation Animation APIs f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list team-design Owned by Design Languages team triaged-design Triaged by Design Languages team
Projects
None yet
Development

No branches or pull requests

9 participants