Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CupertinoSliverRefreshControl in NestedScrollView

In my app i need complex scroll views. As horizontal lists inside of vertical list and animated headers. The code below is a minimalistic sample that makes my problem reproducible on iOS devices.

I have problems with nested scrollviews in flutter. if i use SliverOverlapAbsorber and SliverOverlapInjector the used CupertinoSliverRefreshControl (the progress indicator) doesn't show up on pull down.

So i replaced it with a red Container. It seams like it's shifted to the top so it's below the appbar. When I set pinned to false in the SliverAppBar it's showing correct, but i need the appbar to stay. I don't get what the pinned parameter has to do with that.

Also, if i put less items in my SliverFixedExtentList (let's say 5 instead of 50) the CupertinoSliverRefreshControl it's not possible to pull down at all (no scrolling, also only not working with the overlap observer/injector used).

Can anyone help me, why this is happening or has an alternative for the overlap observer/injector?

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
    
    class TestScrollRefresh extends StatefulWidget {
      const TestScrollRefresh({Key? key}) : super(key: key);
    
      @override
      State<TestScrollRefresh> createState() => _TestScrollRefreshState();
    }
    
    class _TestScrollRefreshState extends State<TestScrollRefresh> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool isBoxScrolled) {
              return [
                SliverOverlapAbsorber(
                  handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                  sliver: SliverAppBar(
                    title: Text("Title"),
                    forceElevated: isBoxScrolled,
                    pinned: true,
                  ),
                ),
              ];
            },
            body: Builder(
              builder: (BuildContext context) {
                final innerScrollController = PrimaryScrollController.of(context);

            return CustomScrollView(
              controller: innerScrollController,
              slivers: <Widget>[
                _refreshIndicator(),
                SliverOverlapInjector(
                  handle:
                      NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                ),
                SliverFixedExtentList(
                  itemExtent: 48.0,
                  delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                      return ListTile(title: Text('Item $index'));
                    },
                    childCount: 50,
                  ),
                ),
              ],
            );
          },
        ),
      ),
    );
  }

  Future<bool> refresh() async {
    print('wait for service to refresh dummy');
    await Future<void>.delayed(const Duration(milliseconds: 5000));
    return false;
  }

  _refreshIndicator() {
    return CupertinoSliverRefreshControl(
      onRefresh: () => refresh(),
      builder: (BuildContext context, RefreshIndicatorMode refreshState, double pulledExtent, double refreshTriggerPullDistance, double refreshIndicatorExtent,){
        return Container(color: Colors.red,);
      },
    );
  }
}
like image 951
Helmut Starz Avatar asked Oct 23 '25 06:10

Helmut Starz


1 Answers

I was able to address this issue by using the builder property of CupertinoSliverRefreshControl:

        CupertinoSliverRefreshControl(
          onRefresh: onRefresh,
          builder: (context, refreshState, pulledExtent, refreshTriggerPullDistance, refreshIndicatorExtent) {
            return Padding(
              padding: const EdgeInsets.only(top: 100),
              child: CupertinoSliverRefreshControl.buildRefreshIndicator(
                context,
                refreshState,
                pulledExtent,
                refreshTriggerPullDistance,
                refreshIndicatorExtent,
              ),
            );
          },
        ),

This GitHub comment also helped me better understand the usage of NestedScrollView.

like image 125
Joe Muller Avatar answered Oct 25 '25 23:10

Joe Muller



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!