GithubHelp home page GithubHelp logo

idootop / custom_nested_scroll_view Goto Github PK

View Code? Open in Web Editor NEW
39.0 39.0 27.0 716 KB

A Flutter NestedScrollView that supports outer scroller to top overscroll.

Home Page: https://flutter-nested-scroll-view-plus.vercel.app

License: MIT License

Kotlin 0.11% Swift 0.98% Objective-C 0.03% Dart 95.74% HTML 3.14%
flutter

custom_nested_scroll_view's Introduction

Del.Wang

custom_nested_scroll_view's People

Contributors

idootop avatar smihica avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

custom_nested_scroll_view's Issues

Flutter 3.0.0 | Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.

: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.

  • 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../fvm/versions/3.0.0/packages/flutter/lib/src/scheduler/binding.dart').
    SchedulerBinding.instance!.addPostFrameCallback(
    ^
    Restarted application in 3,635ms.
    flutter: ^[[38;5;12m┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────<…>
    flutter: ^[[38;5;12m│ #0 AuthGuard.onNavigation (package:fullpass/routes/auth_guard.dart:15:14)<…>
    flutter: ^[[38;5;12m│ #1 StackRouter._canNavigate (package:auto_route/src/router/controller/routing_controller.dart:1093:13)<…>
    flutter: ^[[38;5;12m├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄<…>
    flutter: ^[[38;5;12m│ 💡 AuthAuthorizedState()<…>
    flutter: ^[[38;5;12m└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────<…>

Might be causing build issue on Flutter master channel 3.9.0-15.0.pre.22

I'm getting ane error (Xcode):
../../../.pub-cache/git/custom_nested_scroll_view-74a3a7163278c8e84
18ba359d94f6448196d0b25/lib/src/nested_scroll_view.dart:526:24:
Error: The method '_NestedScrollMetrics.copyWith' doesn't have the
named parameter 'devicePixelRatio' of overridden method 'Object
with ScrollMetrics.copyWith'.

I have no issues on stable.

Incompatibility of plugin with Flutter 3.7.0-13.0.pre.79 leads to build failure

I'm using Flutter master branch, and I just pulled the lastest update and try starting my app, however I got an error from this plugin file.

My Flutter and Dart version info is below:

Flutter 3.7.0-13.0.pre.79 • channel master • https://github.com/flutter/flutter.git
Framework • revision 91c3f80c8c (15 hours ago) • 2022-12-27 04:44:24 -0500
Engine • revision 790604a09f
Tools • Dart 3.0.0 (build 3.0.0-64.0.dev) • DevTools 2.20.0

And in this version of Flutter, after I tried to start my app, I got this error (I tried flutter clean and pub get however the problem still there):

Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
lib\main.dart:1
: Error: The method '_NestedScrollMetrics.copyWith' doesn't have the named parameter 'devicePixelRatio' of overridden method 'Object with ScrollMetrics.copyWith'.
../…/src/nested_scroll_view.dart:526
  _NestedScrollMetrics copyWith({
                       ^
/C:/flutter/packages/flutter/lib/src/widgets/scroll_metrics.dart:43:17: Context: This is the overridden method ('copyWith').
  ScrollMetrics copyWith({
                ^

: Error: The superclass, 'FixedScrollMetrics', has no unnamed constructor that takes no arguments.
../…/src/nested_scroll_view.dart:514
  _NestedScrollMetrics({
  ^^^^^^^^^^^^^^^^^^^^
Target kernel_snapshot failed: Exception
2

FAILURE: Build failed with an exception.

* Where:
Script 'C:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 1157

* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 16s
Exception: Gradle task assembleDebug failed with exit code 1
Exited (sigterm)

Layout render exception

Describe the issue:

When user overscrolls, a layout exception is thrown

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
SliverGeometry is not valid: The "scrollExtent" is negative.
The RenderSliver that returned the offending geometry was: _RenderSliverOverlapAbsorberX#c28e4 relayoutBoundary=up1 NEEDS-PAINT:
  needs compositing
  creator: CustomSliverOverlapAbsorber ← _ProfileSliverAppBar ← BlocListener<AuthWatcherCubit,
    AuthWatcherState> ← BlocSelector<AuthWatcherCubit, AuthWatcherState, User?> ←
    _NestedScrollViewViewport ← IgnorePointer-[GlobalKey#eb7c8] ← Semantics ← Listener ←
    _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#e565b] ←
    Listener ← _ScrollableScope ← ⋯
  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.forward,
    scrollOffset: 0.0, remainingPaintExtent: 748.0, overlap: -148.0, crossAxisExtent: 414.0,
    crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 896.0, remainingCacheExtent:
    998.0, cacheOrigin: 0.0)
  geometry: SliverGeometry(scrollExtent: -0.0, paintExtent: 296.0, paintOrigin: -148.0, layoutExtent:
    148.0, maxPaintExtent: 296.0, hasVisualOverflow: true, cacheExtent: 148.0)
  handle: _SliverOverlapAbsorberHandle(0.0null)

The relevant error-causing widget was:
  CustomSliverOverlapAbsorber
  CustomSliverOverlapAbsorber:file:///Users/brendan/Mobile/FlutterProjects/sorosoke/lib/features/dashboard/presentation/screens/profile_sc
  reen.dart:125:12

When the exception was thrown, this was the stack:
#0      SliverGeometry.debugAssertIsValid.<anonymous closure>.verify (package:flutter/src/rendering/sliver.dart:712:9)
#1      SliverGeometry.debugAssertIsValid.<anonymous closure> (package:flutter/src/rendering/sliver.dart:721:7)
#2      SliverGeometry.debugAssertIsValid (package:flutter/src/rendering/sliver.dart:751:6)
#3      RenderSliver.debugAssertDoesMeetConstraints (package:flutter/src/rendering/sliver.dart:1205:22)
#4      RenderObject.layout.<anonymous closure> (package:flutter/src/rendering/object.dart:2138:9)
#5      RenderObject.layout (package:flutter/src/rendering/object.dart:2140:8)
#6      RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:516:13)
#7      RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:1600:12)
#8      RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1507:20)
#9      RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1973:7)
#10     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:999:18)
#11     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:513:19)
#12     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884:13)
#13     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#14     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#15     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#16     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#20     _invoke (dart:ui/hooks.dart:150:10)
#21     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#22     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)

The following RenderObject was being processed when the exception was fired: _RenderSliverOverlapAbsorberX#c28e4 relayoutBoundary=up1
NEEDS-PAINT:
  needs compositing
  creator: CustomSliverOverlapAbsorber ← _ProfileSliverAppBar ← BlocListener<AuthWatcherCubit,
    AuthWatcherState> ← BlocSelector<AuthWatcherCubit, AuthWatcherState, User?> ←
    _NestedScrollViewViewport ← IgnorePointer-[GlobalKey#eb7c8] ← Semantics ← Listener ←
    _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#e565b] ←
    Listener ← _ScrollableScope ← ⋯
  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.forward,
    scrollOffset: 0.0, remainingPaintExtent: 746.7, overlap: -149.3, crossAxisExtent: 414.0,
    crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 896.0, remainingCacheExtent:
    996.7, cacheOrigin: 0.0)
  geometry: SliverGeometry(scrollExtent: -1.3, paintExtent: 297.3, paintOrigin: -149.3, layoutExtent:
    148.0, maxPaintExtent: 297.3, hasVisualOverflow: true, cacheExtent: 148.0)
  handle: _SliverOverlapAbsorberHandle(0.0null)
This RenderObject had the following descendants (showing up to depth 5):
    child: _RenderSliverPinnedPersistentHeaderForWidgets#10042 relayoutBoundary=up2 NEEDS-PAINT
      child: RenderSemanticsAnnotations#f31e0 relayoutBoundary=up3 NEEDS-PAINT
        child: RenderAnnotatedRegion<SystemUiOverlayStyle>#434e1 relayoutBoundary=up4 NEEDS-PAINT
          child: RenderPhysicalModel#bf5d5 relayoutBoundary=up5 NEEDS-PAINT
            child: _RenderInkFeatures#eba97 relayoutBoundary=up6 NEEDS-PAINT
════════════════════════════════════════════════════════════════════════════════════════════════════

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Another exception was thrown: SliverGeometry is not valid: The "scrollExtent" is negative.

Steps to Reproduce:

Use the default example in the Readme.md

  • Change minHeight to 100
  • Change maxHeight to 120
  • Pull down the ScrollView past 120 (maxHeight)
  • Platform - iOS
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: CustomNestedScrollView(
          overscrollType: CustomOverscroll.outer,
          // !important
          physics: const BouncingScrollPhysics(
            parent: AlwaysScrollableScrollPhysics(),
          ),
          headerSliverBuilder: (context, innerScrolled) => <Widget>[
            MySliverAppBar(),
          ],
          body: TabBarView(
            children: [
              CustomScrollView(
                // !important
                physics: const BouncingScrollPhysics(
                  parent: AlwaysScrollableScrollPhysics(),
                ),
                slivers: <Widget>[
                  TopOverlapInjector(),
                  // scroll view
                  SliverFixedExtentList(
                    delegate: SliverChildBuilderDelegate(
                      (_, index) => ListTile(
                        key: Key('$index'),
                        title: Center(
                          child: Text('ListTile ${index + 1}'),
                        ),
                      ),
                      childCount: 30,
                    ),
                    itemExtent: 50,
                  ),
                ],
              ),
              CustomScrollView(
                physics: NeverScrollableScrollPhysics(),
                slivers: <Widget>[
                  TopOverlapInjector(),
                  // some widget
                  SliverFillRemaining(
                    child: Center(
                      child: Text('Test'),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class TopOverlapInjector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Builder(
      builder: (context) => CustomSliverOverlapInjector(
        overscrollType: CustomOverscroll.outer,
        handle: CustomNestedScrollView.sliverOverlapAbsorberHandleFor(context),
      ),
    );
  }
}

class MySliverAppBar extends StatelessWidget {
  ///Header collapsed height
  final minHeight = 100.0;

  ///Header expanded height
  final maxHeight = 120.0;

  final tabBar = TabBar(
    tabs: <Widget>[Text('Tab1'), Text('Tab2')],
  );

  @override
  Widget build(BuildContext context) {
    final topHeight = MediaQuery.of(context).padding.top;
    return CustomSliverOverlapAbsorber(
      overscrollType: CustomOverscroll.outer,
      handle: CustomNestedScrollView.sliverOverlapAbsorberHandleFor(
        context,
      ),
      sliver: SliverAppBar(
        pinned: true,
        stretch: true,
        toolbarHeight: minHeight - tabBar.preferredSize.height - topHeight,
        collapsedHeight: minHeight - tabBar.preferredSize.height - topHeight,
        expandedHeight: maxHeight - topHeight,
        flexibleSpace: FlexibleSpaceBar(
          centerTitle: true,
          title: Center(child: Text('Example')),
          stretchModes: <StretchMode>[
            StretchMode.zoomBackground,
            StretchMode.blurBackground,
          ],
          background: Image.network(
            'https://pic1.zhimg.com/80/v2-fc35089cfe6c50f97324c98f963930c9_720w.jpg',
            fit: BoxFit.cover,
          ),
        ),
        bottom: tabBar,
      ),
    );
  }
}

breaking changes in flutter 3.4

There are some breaking changes in the API of flutter 3.4:

  1. ScrollActivityDelegate has a new method updateBallisticAnimation which must be implemented
  2. BallisticScrollActivity has a new parameter in its constructor: shouldIgnorePointer

Has someone already looked into this?

Is it possible to avoid scrolling when there is an empty space on the list?

Using the example you provided I changed the list to build two Items.

In this case the list should not scroll.

import 'package:flutter/material.dart';
import 'package:custom_nested_scroll_view/custom_nested_scroll_view.dart';

void main() => runApp(
      MaterialApp(
        title: 'Example',
        home: Example(),
      ),
    );

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

  @override
  State<Example> createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: CustomNestedScrollView(
          // use key to access CustomNestedScrollViewState
          key: myKey,
          headerSliverBuilder: (context, innerScrolled) => <Widget>[
            // use CustomOverlapAbsorber to wrap your SliverAppBar
            CustomOverlapAbsorber(
              sliver: MySliverAppBar(),
            ),
          ],
          body: TabBarView(
            children: [
              CustomScrollView(
                slivers: <Widget>[
                  // use CustomOverlapInjector on top of your inner CustomScrollView
                  CustomOverlapInjector(),
                  _tabBody1,
                ],
              ),
              CustomScrollView(
                slivers: <Widget>[
                  // use CustomOverlapInjector on top of your inner CustomScrollView
                  CustomOverlapInjector(),
                  _tabBody2,
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  final GlobalKey<CustomNestedScrollViewState> myKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      // use GlobalKey<CustomNestedScrollViewState> to access inner or outer scroll controller
      myKey.currentState?.innerController.addListener(() {
        final innerController = myKey.currentState!.innerController;
        print('>>> Scrolling inner nested scrollview: ${innerController.positions}');
      });
      myKey.currentState?.outerController.addListener(() {
        final outerController = myKey.currentState!.outerController;
        print('>>> Scrolling outer nested scrollview: ${outerController.positions}');
      });
    });
  }

  final _tabBody1 = SliverFixedExtentList(
    delegate: SliverChildBuilderDelegate(
      (_, index) => ListTile(
        key: Key('$index'),
        title: Center(
          child: Text('ListTile ${index + 1}'),
        ),
      ),
      childCount: 2,
    ),
    itemExtent: 50,
  );

  final _tabBody2 = const SliverFillRemaining(
    child: Center(
      child: Text('Test'),
    ),
  );
}

class MySliverAppBar extends StatelessWidget {
  ///Header collapsed height
  final minHeight = 120.0;

  ///Header expanded height
  final maxHeight = 400.0;

  final tabBar = const TabBar(
    tabs: <Widget>[Text('Tab1'), Text('Tab2')],
  );

  @override
  Widget build(BuildContext context) {
    final topHeight = MediaQuery.of(context).padding.top;
    return SliverAppBar(
      pinned: true,
      stretch: true,
      toolbarHeight: minHeight - tabBar.preferredSize.height - topHeight,
      collapsedHeight: minHeight - tabBar.preferredSize.height - topHeight,
      expandedHeight: maxHeight - topHeight,
      flexibleSpace: FlexibleSpaceBar(
        centerTitle: true,
        title: const Center(child: Text('Example')),
        stretchModes: <StretchMode>[
          StretchMode.zoomBackground,
          StretchMode.blurBackground,
        ],
        background: Image.network(
          'https://pic1.zhimg.com/80/v2-fc35089cfe6c50f97324c98f963930c9_720w.jpg',
          fit: BoxFit.cover,
        ),
      ),
      bottom: tabBar,
    );
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.