Search code examples
flutterlistview

RefreshIndicator not working with ListView in flutter


Platform: Flutter web Hi, I am having difficulty in getting the Listview to call the refreshindicator at all. Issue is I cannot refresh the data on the screen using the indicator. What is weird is that my listview is not responding to my mouse drag but it DOES scroll using the wheel in the mouse. Not sure if that is relevant. Given below is the code:


class QuestionListPage extends StatefulWidget {
  final int id;
  QuestionListPage(this.id);

  @override
  createState() => _QuestionListPageState(this.id);
}

class _QuestionListPageState extends State<QuestionListPage> {
  final int id;
  List<Question> questions = [];

  _QuestionListPageState(this.id);

  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
      GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback(((timeStamp) {
      showDialog(
        context: context,
        builder: (context) {
          return const Center(
              child: CircularProgressIndicator(
            strokeWidth: 10, //strokewidth makes it fatter.
            backgroundColor: Colors.white,
            color: Colors.blue,
          ));
        },
      );
    }));
    loadData();
  }

  loadData() async {
    dynamic questionsList;
    try {
      questionsList = await QuestionController.fetchByModule(id);
    } catch (e) {
      await alertDialogShow("Error", "$e");
    }
    if (mounted) {
      Navigator.of(context).pop();
      setState(() {
        this.questions = questionsList;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "Questions",
          style: TextStyle(color: Colors.white),
          textAlign: TextAlign.left,
        ),
        actions: [
          Padding(
              padding: const EdgeInsets.only(right: 20.0),
              child: GestureDetector(
                onTap: () {
                  //moved to question type
                  // _navigateQuestionTypePage(context);
                  _navigateNewQuestionPage(context);
                },
                child: const Icon(
                  // Icons.fiber_new_outlined,
                  Icons.add_box_outlined,
                  size: 26.0,
                ),
              )),
        ],
      ),
      body: RefreshIndicator(
        key: _refreshIndicatorKey,
        triggerMode: RefreshIndicatorTriggerMode.anywhere,
        edgeOffset: 40,
        displacement: 200,
        strokeWidth: 10,
        color: Colors.white,
        backgroundColor: Colors.blue,
        onRefresh: () async {
          await loadData();
        },
        child: Stack(
          children: <Widget>[
            ListView.builder(
              physics: AlwaysScrollableScrollPhysics(),
              itemCount: questions.length,
              itemBuilder: _listViewItemBuilder,
            ),
          ],
        ),
      ),
    );
  }

  void _navigateNewQuestionPage(BuildContext context) {
    Navigator.push(
        context, MaterialPageRoute(builder: (context) => NewQuestionPage(id)));
  }

  Widget _listViewItemBuilder(BuildContext context, int index) {
    final question = questions[index];
    return ListTile(
      contentPadding: const EdgeInsets.all(10.0),
      title: Text('Question: ${question.question_text}',
          maxLines: 2,
          style: const TextStyle(
              fontWeight: FontWeight.bold, fontSize: 12, color: Colors.black),
          textAlign: TextAlign.left),
      subtitle: Text(
        'Type: ${question.type}',
        style: const TextStyle(
            fontWeight: FontWeight.normal, fontSize: 12, color: Colors.black),
      ),
      trailing: IconButton(
          icon: const Icon(Icons.info_outline_rounded),
          onPressed: () =>
              _navigateToModuleDetail(context, questions[index].id!)),
    );
  }

  void _navigateToModuleDetail(BuildContext context, int questionID) {
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => QuestionDetailPage(questionID)));
  }

  alertDialogShow(String titleString, String detailString) async {
    return await showDialog<String>(
      context: context,
      builder: (BuildContext context) => AlertDialog(
        title: Text(titleString),
        content: Text(detailString),
        actions: <Widget>[
          TextButton(
            style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(HexColor("0039A6"))),
            onPressed: () => Navigator.pop(context, 'OK'),
            child: const Text(
              'OK',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ],
      ),
    );
  }
}


Solution

  • So my question was specifically for Flutter web. This is a known bug for people that done know. The alternative is to use one of dart packages: https://pub.dev/packages/liquid_pull_to_refresh

    i updated the code to use the:

     body: LiquidPullToRefresh(
            key: _refreshIndicatorKey,
            color: Colors.white,
            backgroundColor: Colors.blue,
            onRefresh: () async {
              await loadData();
            },
            child: Stack(
              children: <Widget>[
                ListView.builder(
                  scrollDirection: Axis.vertical,
                  physics: AlwaysScrollableScrollPhysics(),
                  itemCount: questions.length,
                  itemBuilder: _listViewItemBuilder,
                ),
              ],
            ),
          ),
    

    Worked like a charm.