aagarwal1012 / Liquid-Pull-To-Refresh

🔁 A custom refresh indicator for flutter.
https://pub.dev/packages/liquid_pull_to_refresh
MIT License
1.25k stars 91 forks source link

Cannot refresh if not enough elements in ListView.builder #17

Closed dukaric1991 closed 5 years ago

dukaric1991 commented 5 years ago

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:

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(),
                      );
                    },
                  ), 
                ),
dukaric1991 commented 5 years ago

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

Taormina commented 5 years ago

Can we see the implementation of your _controller?

dukaric1991 commented 5 years ago

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(),
                        );
                      },
                    ),
                ),
    );
  }
Taormina commented 5 years ago

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

aagarwal1012 commented 5 years ago

@dukaric1991, any updates regarding this issue?

aagarwal1012 commented 5 years ago

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

sijav commented 5 years ago

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 5 years ago

@aagarwal1012 any updates?

rodrigomoretto commented 4 years ago

I'm still facing this issue. Any updates?

rodrigomoretto commented 4 years ago

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()
)