extended_nested_scroll_view

repository·master·Indexed 20 days ago

https://github.com/fluttercandies/extended_nested_scroll_view

An enhanced implementation of Flutter's NestedScrollView that resolves issues with pinned headers, TabView scroll synchronization, and ScrollController constraints. It provides tools like pinnedHeaderSliverHeightBuilder for header height calculation, the onlyOneScrollInBody property for scroll position management, and ExtendedVisibilityDetector for tracking widget visibility within nested views.

Tokens
1.2K
Snippets
5
Records
7
Agent score
21%

What's inside extended_nested_scroll_view

  1. Overview of extended_nested_scroll_view

    master

    The extended_nested_scroll_view package provides an enhanced version of Flutter's NestedScrollView to resolve several known limitations in the standard implementation. It specifically addresses:

    1. Pinned Sliver Header Issues: Provides a way to calculate and provide the total height of pinned sliver headers.
    2. Inner Scrollable Sync Issues: Improves synchronization for scrollables within a TabView.
    3. ScrollController Constraints: Enables common scroll behaviors (like pull-to-refresh, load more, and scroll-to-top) in the NestedScrollView body without requiring a manual ScrollController, which would otherwise break the internal InnerScrollController logic.
  2. Manage scroll position sync with onlyOneScrollInBody

    master

    When using ExtendedNestedScrollView with multiple scrollable bodies (like in a TabView), use the onlyOneScrollInBody property to control how scroll positions are handled:

    • Set onlyOneScrollInBody: true: Use this when using AutomaticKeepAliveClientMixin. It prevents ScrollPosition from being disposed and allows the widget to track which specific list is currently active.
    • Set onlyOneScrollInBody: false: Use this when using PageStorageKey. In this mode, ScrollPosition will be disposed, and PageStorageKey will be used to record position info, while ExtendedNestedScrollView maintains a single scroll position.
    ExtendedNestedScrollView(
      onlyOneScrollInBody: true,
    )
  3. Implement scroll behaviors without a ScrollController

    master

    Because assigning a custom ScrollController to a list inside a NestedScrollView body breaks the internal InnerScrollController behavior, you should use the patterns provided by this package to implement common features.

    Reference the following implementation patterns in the repository examples:

    • Pull to refresh
    • Load more
    • Scroll to top
    • Dynamic pinned header height (changing header height dynamically)
  4. Calculate pinned sliver header height with pinnedHeaderSliverHeightBuilder

    master

    To fix issues related to pinned sliver headers, use the pinnedHeaderSliverHeightBuilder callback in ExtendedNestedScrollView. This allows you to return the total height of all pinned sliver headers (e.g., status bar height + AppBar height + TabBar height).

    var tabBarHeight = primaryTabBar.preferredSize.height;
    var pinnedHeaderHeight = statusBarHeight + kToolbarHeight;
    
    ExtendedNestedScrollView(
      pinnedHeaderSliverHeightBuilder: () {
        return pinnedHeaderHeight;
      },
    ),
  5. Identify visible lists with ExtendedVisibilityDetector

    master

    Use ExtendedVisibilityDetector to wrap your scrollable children (like ListView) to determine which specific list is currently visible within the nested view. This requires a uniqueKey to distinguish between different lists.

    ExtendedVisibilityDetector(
      uniqueKey: const Key('Tab1'),
      child: ListView(),
    )
  6. Use ExtendedVisibilityDetector to track widget visibility

    master

    The ExtendedVisibilityDetector is a wrapper around the visibility_detector package that allows you to track the visibility state of a widget and access that state from its descendants using a BuildContext lookup.

    To use it, wrap your target widget with ExtendedVisibilityDetector and provide a uniqueKey (which is passed to the underlying VisibilityDetector). This allows you to query the current VisibilityInfo anywhere in the widget tree below the detector using the ExtendedVisibilityDetector.of(context) method.

    ExtendedVisibilityDetector(
      uniqueKey: Key('my-unique-key'),
      child: MyWidget(),
    )
    
    // Later in a descendant widget:
    final visibilityInfo = ExtendedVisibilityDetector.of(context);
    if (visibilityInfo != null) {
      print('Visibility fraction: ${visibilityInfo.visibleFraction}');
    }
  7. Access visibility state with ExtendedVisibilityDetector.of()

    master

    You can retrieve the most recent VisibilityInfo for an ExtendedVisibilityDetector from any descendant widget by calling the static method ExtendedVisibilityDetector.of(context).

    This method performs an ancestor lookup for the _ExtendedVisibilityDetectorState. If an ancestor of the provided context is an ExtendedVisibilityDetector, it returns the current VisibilityInfo?. If no such ancestor is found, it returns null.

    static VisibilityInfo? of(BuildContext context) {
        return context
            .findAncestorStateOfType<_ExtendedVisibilityDetectorState>()
            ?._visibilityInfo;
    }