skip to Main Content

I’m doing something like a news feed and I’m using CustomScrollView with two slivers (one for initially loaded news and one for new news that should not shift elements when loaded).

Example:

return CustomScrollView(
  center: centerKey,
  slivers: [
    renderOneList(newItems),
    renderOneList(oldItems, centerKey),
  ],
);

Everything works as it should. I use UniqueKey to define the first element where the initial reading starts. Once every X seconds, I load new items and put them into an array of newItems. They are added to the top and the user can scroll to the top.

However, when clicking on the status bar in iOS Primary Scroll Controller scrolls to position 0 (which in my case is the boundary of new news and old news). This is correct from Flutter’s point of view, but it’s not the behavior I would like to achieve. Any ideas on how to scroll to the top?

What I think about it:

  1. It is possible to move records from oldItems to newItems when scrolling up, but that would cause a lot of redraws and I probably wouldn’t be able to guess the timing of the swap.
  2. While tapping on the status bar, scroll up X pixels in Y milliseconds. Doesn’t seem like a great option either.

I ended up with a dead end, but I’m sure the community has solved such a basic problem before. Hope for some help.

2

Answers


  1. // try this one
    
    ScrollController sc = ScrollController();
    
    @override
    void initState() {
      super.initState();
      sc.addListener(() {
        if (sc.offset <= 0) {
          // Implement your custom scrolling logic here
        }
      });
    }
    
    // ...
    
    return CustomScrollView(
      controller: sc,
      slivers: [
        renderOneList(newItems),
        renderOneList(oldItems),
      ],
    );
    
    Login or Signup to reply.
  2. when tapping the status bar, you can achieve this by using the primary property of the CustomScrollView and a combination of ScrollController and ScrollPhysics.

    primary: true, // Add this line before the slivers property

    Customize Scroll Physics
    Create a custom scroll physics class that allows overscrolling at the top but snaps back to the top when released.

    class CustomScrollPhysics extends ScrollPhysics {
      const CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);
    
      @override
      CustomScrollPhysics applyTo(ScrollPhysics ancestor) {
        return CustomScrollPhysics(parent: buildParent(ancestor));
      }
    
      @override
      Simulation createBallisticSimulation(
          ScrollMetrics position, double velocity) {
        // Prevent overscrolling at the top and snap back to the top
        if (position.pixels <= position.minScrollExtent) {
          return ScrollSpringSimulation(
            spring,
            position.pixels,
            position.minScrollExtent,
            0.0,
            tolerance: tolerance,
          );
        }
        return super.createBallisticSimulation(position, velocity);
      }
    }
    

    Wrap the CustomScrollView with NotificationListener

    NotificationListener<UserScrollNotification>(
      onNotification: (notification) {
        if (notification.direction == ScrollDirection.idle) {
          if (notification.metrics.atEdge && notification.metrics.pixels == 0.0) {
            // Scroll to the top of the CustomScrollView
            _scrollController.animateTo(
              _scrollController.position.minScrollExtent,
              duration: Duration(milliseconds: 500),
              curve: Curves.easeInOut,
            );
          }
        }
        return false;
      },
      child: CustomScrollView(
        controller: _scrollController,
        physics: CustomScrollPhysics(),
        slivers: [
          renderOneList(newItems),
          renderOneList(oldItems),
        ],
      ),
    )
    

    CustomScrollPhysics allows overscrolling at the top while ensuring that the scrolling animation snaps back to the top when releases the touch.
    The NotificationListener captures the status bar tap and initiates the scrolling to the top.

    Remember to manage the _scrollController properly, including disposing it in the dispose method.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search