aagarwal1012/Liquid-Pull-To-Refresh

Cannot refresh if not enough elements in ListView.builder

dukaric1991 opened this issue · 10 comments

When there are enough(you can scroll) items in Listview.builder the pull to refresh is working, but if there are lets say 2 elements(not enough items to scroll) in ListView.builder the pull to refresh stops working like it isnt even there...

Flutter:

  • 1.5.4-hotfix2
  • stable
LiquidPullToRefresh(
                  scrollController: _controller,
                  onRefresh: () => store.matchStore.fetchMatches(true),
                  showChildOpacityTransition: true,
                  height: 100,
                  color: Colors.yellow,
                  backgroundColor: Colors.black,
                   child: ListView.builder(
                    itemCount: store.matchStore.listOfMatches.length+1,
                    itemBuilder: (context, index) {
                      if (index == 0) return DropDownWidget();
                      MatchClass match = store.matchStore.listOfMatches[index-1];
                      return MatchCard(
                        match: match,
                        cardKey: new GlobalKey(),
                      );
                    },
                  ), 
                ),

When i remove scrollController: _controller, it start to work, but i need scrollController...

Can we see the implementation of your _controller?

If i have _controller then pull to refresh only works if there are enough elements in ListView.builder so you can scroll. But when there is only 1 or 2 elements in ListView.builder and its not scrollable then pull to refresh doesnt work. But if i remove _controller it works in both situations.

Thats my implementation:

class NewsFeedScreen extends StatefulWidget {
  @override
  _NewsFeedScreenState createState() => new _NewsFeedScreenState();
}

class _NewsFeedScreenState extends State<NewsFeedScreen> {
  bool loadingInvite = false;
  ScrollController _controller;
  bool buttonShown = true;

  _scrollListener() {
    if (_controller.offset >= _controller.position.maxScrollExtent &&
        !_controller.position.outOfRange &&
        buttonShown) {
      Provider.of<MobxStore>(context).setShowAddMatchButton(false);
      buttonShown = false;
    }
    if (_controller.offset <= _controller.position.maxScrollExtent - 50 &&
        !_controller.position.outOfRange &&
        !buttonShown) {
      Provider.of<MobxStore>(context).setShowAddMatchButton(true);
      buttonShown = true;
    }
  }

  void _scrollToTop() async {
    if (_controller.hasClients) {
      await _controller.animateTo(0.0,
          duration: Duration(milliseconds: 1), curve: Curves.linear);
    }
  }

  @override
  void initState() {
    _controller = ScrollController();
    _controller.addListener(_scrollListener);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final store = Provider.of<MobxStore>(context);

    if (store.matchStore.justAddedMatch &&
        store.matchStore.successfullyAddedMatch) {
      showNotification(context);
      _scrollToTop();
    }

    return Observer(
      builder: (_) => store.loading
          ? Column(
              children: <Widget>[
                Container(
                    margin: EdgeInsets.fromLTRB(
                        0, 0, 0, Constants.phoneHeight * 0.04),
                    child: DropDownWidget()),
                Center(child: CircularProgressIndicator()),
              ],
            )
          : store.matchStore.listOfMatches.length == 0
              ? LiquidPullToRefresh(
                  onRefresh: () => store.matchStore.fetchMatches(true),
                  showChildOpacityTransition: true,
                  height: 100,
                  color: Colors.yellow,
                  backgroundColor: Colors.black,
                  child: ListView.builder(
                      controller: _controller,
                      itemCount: 1,
                      itemBuilder: (context, index) {
                        return Column(
                          children: <Widget>[
                            DropDownWidget(),
                            //NO DATA TO DISPLAY========================
                            NothingToShow(
                              icon: Icons.line_weight,
                              text: FlutterI18n.translate(
                                  context, "no_matches_yet_label"),
                              additionalChild: Container(
                                margin: EdgeInsets.fromLTRB(
                                    0, Constants.phoneHeight * 0.01, 0, 0),
                                height: Constants.phoneHeight * 0.06,
                                child: loadingInvite == false
                                    ? RaisedButton.icon(
                                        icon: Icon(Icons.person_add),
                                        onPressed: () => _invitePlayer(),
                                        elevation: 0.3,
                                        textColor: Colors.black,
                                        color: Colors.yellow,
                                        label: Text(
                                          FlutterI18n.translate(
                                              context, "share_button_text"),
                                          style: TextStyle(
                                              fontSize: Constants.phoneHeight *
                                                  0.019),
                                        ),
                                      )
                                    : SpinKitRing(
                                        lineWidth: 3.0,
                                        color: Colors.black,
                                        size: 30),
                              ),
                            ),
                          ],
                        );
                      }),
                )
              //NEWS FEED DATA============================================================
              : LiquidPullToRefresh(
                  scrollController: _controller,
                  onRefresh: () => store.matchStore.fetchMatches(true),
                  showChildOpacityTransition: true,
                  height: Constants.phoneHeight * 0.13,
                  color: Colors.yellow,
                  backgroundColor: Colors.black,
                  child: ListView.builder(
                      controller: _controller,
                      itemCount: store.matchStore.listOfMatches.length + 1,
                      itemBuilder: (context, index) {
                        if (index == 0) return DropDownWidget();
                        
                        MatchClass match =
                            store.matchStore.listOfMatches[index - 1];
                        return MatchCard(
                          match: match,
                          cardKey: new GlobalKey(),
                        );
                      },
                    ),
                ),
    );
  }

Hrmm, I wonder if using the same _controller for both the parent (LiquidPullToRefresh) and the child (ListView) is causing a conflict in behaviors....

@dukaric1991, any updates regarding this issue?

I am closing this issue for now. Feel free to reopen this issue if any problem arises.

sijav commented

we have the same problem with only one scrollController in LiquidPullToRefresh we cannot pull to refresh if there's not enough elements and does not scroll

sijav commented

@aagarwal1012 any updates?

I'm still facing this issue. Any updates?

Just found out a solution.
As mentioned here: https://stackoverflow.com/questions/48081917/flutter-listview-not-scrollable-not-bouncing
Specifically this answer: https://stackoverflow.com/a/48099351
You need to use a AlwaysScrollableScrollPhysics on the physics property from ListView

ListView(
  physics: AlwaysScrollableScrollPhysics(),
  child: yourWidget()
)