如何在刷新指示器隐藏后正确显示Snackbar

发布于 2025-02-10 06:55:35 字数 2407 浏览 2 评论 0原文

我有RefresHindicator及其内部listView,因此RefresHindicatorlist> listView 上工作,我也设置了<代码> globalkey&lt; refreshindicatorState&gt;() to felreshindicator,以便我可以在按钮点击上显示指示器。

一切都是拳头

  final _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();

  @override
  Widget build(BuildContext context) {
        return RefreshIndicator(
          key: _refreshIndicatorKey,
          onRefresh: _onRefresh,
          child: buidlListView(snapshot),
        );
  }

  Widget buidlListView(AsyncSnapshot<List<Model>> snapshot) {
    if (snapshot.hasData && snapshot.data!.isNotEmpty) {
      return buildModelList(snapshot);
    }

    return buildNoModelList();
  }

  Widget buildNoModelList() {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: _onRefresh,
          child: const SizedBox(
          width: double.infinity,
          child: Text('Refresh', textAlign: TextAlign.center),
        ),
      ],
    );
  }

  Widget buildModelList(
    AsyncSnapshot<List<Model>> snapshot,
  ) {
    final modelList = snapshot.data!;

    return ListView.separated(
      padding: const EdgeInsets.all(16),
      itemCount: modelList.length,
      separatorBuilder: (context, index) => const SizedBox(height: 16),
      itemBuilder: (context, index) {
        
        final model = modelList[index];
  
        return ModelCard(
          key: ValueKey(model),
          model: model,
        );
      },
    );
  }

  Future<void> _onRefresh() async {
    // ignore: unawaited_futures
    _refreshIndicatorKey.currentState?.show();

    final isModelExist = await loadModels();

    // not returning this because i want to show snack bar after indicator hides
    Future<void>.delayed(const Duration(seconds: 3));

    if (!isModelExist) {
      showSnackBar();
    }

    return Future.value();
  }

  void showSnackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        behavior: SnackBarBehavior.floating,
        content: Text('No Model Found'),
      ),
    );
  }

  Future<bool> loadModels() async {

  final snapshot = await modelCollectionRef().get();

  if (snapshot.size > 0) {

    //...

    return true;
  }

  return false;
}

i have RefreshIndicator and inside it ListView so that RefreshIndicator work swipe down gesture on ListView, also i have set GlobalKey<RefreshIndicatorState>() to RefreshIndicator so that i can show indicator on button tap.

all is wokring but in _onRefresh i am calling showSnackBar but snakbar showing twice i dont know why

  final _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();

  @override
  Widget build(BuildContext context) {
        return RefreshIndicator(
          key: _refreshIndicatorKey,
          onRefresh: _onRefresh,
          child: buidlListView(snapshot),
        );
  }

  Widget buidlListView(AsyncSnapshot<List<Model>> snapshot) {
    if (snapshot.hasData && snapshot.data!.isNotEmpty) {
      return buildModelList(snapshot);
    }

    return buildNoModelList();
  }

  Widget buildNoModelList() {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: _onRefresh,
          child: const SizedBox(
          width: double.infinity,
          child: Text('Refresh', textAlign: TextAlign.center),
        ),
      ],
    );
  }

  Widget buildModelList(
    AsyncSnapshot<List<Model>> snapshot,
  ) {
    final modelList = snapshot.data!;

    return ListView.separated(
      padding: const EdgeInsets.all(16),
      itemCount: modelList.length,
      separatorBuilder: (context, index) => const SizedBox(height: 16),
      itemBuilder: (context, index) {
        
        final model = modelList[index];
  
        return ModelCard(
          key: ValueKey(model),
          model: model,
        );
      },
    );
  }

  Future<void> _onRefresh() async {
    // ignore: unawaited_futures
    _refreshIndicatorKey.currentState?.show();

    final isModelExist = await loadModels();

    // not returning this because i want to show snack bar after indicator hides
    Future<void>.delayed(const Duration(seconds: 3));

    if (!isModelExist) {
      showSnackBar();
    }

    return Future.value();
  }

  void showSnackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        behavior: SnackBarBehavior.floating,
        content: Text('No Model Found'),
      ),
    );
  }

  Future<bool> loadModels() async {

  final snapshot = await modelCollectionRef().get();

  if (snapshot.size > 0) {

    //...

    return true;
  }

  return false;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

◇流星雨 2025-02-17 06:55:35

请参阅以下示例,

我在下面使用的插件中使用了刷新指示器

pull_to_refresh: ^2.0.0

import 'package:flutter/material.dart';
import 'package:flutter_app_modal_sheet/ProviderModel/ProviderCNModel.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

void main() {
  runApp(
    MyApp(),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /*Controllers*/
  final RefreshController _refreshController =
      RefreshController(initialRefresh: false);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _refreshController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: SmartRefresher(
        controller: _refreshController,
        enablePullDown: true,
        header: MaterialClassicHeader(),
        onRefresh: () async {
          await Future.delayed(const Duration(seconds: 3), () {});
           _refreshController.refreshCompleted();
          showSnackBar();
        },
        child: ListView.builder(
          itemCount: 100,
          itemBuilder: (BuildContext context, int index) {
            return Padding(
              padding: const EdgeInsets.all(10.0),
              child: Text("Index Value: $index"),
            );
          },
        ),
      ),
    );
  }

  void showSnackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        behavior: SnackBarBehavior.floating,
        content: Text('No Model Found'),
      ),
    );
  }
}


Please refer to below example

I have used below mentioned plugin for refresh indicator

pull_to_refresh: ^2.0.0

import 'package:flutter/material.dart';
import 'package:flutter_app_modal_sheet/ProviderModel/ProviderCNModel.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

void main() {
  runApp(
    MyApp(),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /*Controllers*/
  final RefreshController _refreshController =
      RefreshController(initialRefresh: false);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _refreshController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: SmartRefresher(
        controller: _refreshController,
        enablePullDown: true,
        header: MaterialClassicHeader(),
        onRefresh: () async {
          await Future.delayed(const Duration(seconds: 3), () {});
           _refreshController.refreshCompleted();
          showSnackBar();
        },
        child: ListView.builder(
          itemCount: 100,
          itemBuilder: (BuildContext context, int index) {
            return Padding(
              padding: const EdgeInsets.all(10.0),
              child: Text("Index Value: $index"),
            );
          },
        ),
      ),
    );
  }

  void showSnackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        behavior: SnackBarBehavior.floating,
        content: Text('No Model Found'),
      ),
    );
  }
}


無心 2025-02-17 06:55:35

解决了该问题是_refreshindicatorKey.currentState?.show();我在_onrefresh()上调用的问题刷新过程,然后在_ONREFRESH()中,我们正在调用_refreshindicatorKey.currentState?.show();哪个告诉Code> RefreshIndicator 运行回电运行onrefresh也反对_onrefresh(),这就是为什么_ONREFRESH()触发了两次,而Snakcbar显示了两次_refreshindicatorKey.currentState?.show(); on按钮点击,然后refreshindicator它自动运行_ONREFRESH() callback。


  Widget buildNoModelList() {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: () {
            _refreshIndicatorKey.currentState?.show();
          },
          child: const SizedBox(
          width: double.infinity,
          child: Text('Refresh', textAlign: TextAlign.center),
        ),
      ],
    );
  }

  Future<void> _onRefresh() async {
    final isModelExist = await loadModels();

    // not returning this because i want to show snackbar after indicator hides
    await Future<void>.delayed(const Duration(seconds: 3));

    if (!isModelExist) {
      showSnackBar();
    }

    return;
  }

Solved the problem in is _refreshIndicatorKey.currentState?.show(); which i was calling on _onRefresh() and using this method this on button tap so when its first trigger ths refresh process but then in _onRefresh() we are calling _refreshIndicatorKey.currentState?.show(); which tell RefreshIndicator run call back onRefresh which also refrenced to _onRefresh() so thats why _onRefresh() triggred two times and snakcbar showed two times so to solve this i just call _refreshIndicatorKey.currentState?.show(); on button tap and then RefreshIndicator it self run _onRefresh() callback.


  Widget buildNoModelList() {
    return ListView(
      children: [
        ElevatedButton(
          onPressed: () {
            _refreshIndicatorKey.currentState?.show();
          },
          child: const SizedBox(
          width: double.infinity,
          child: Text('Refresh', textAlign: TextAlign.center),
        ),
      ],
    );
  }

  Future<void> _onRefresh() async {
    final isModelExist = await loadModels();

    // not returning this because i want to show snackbar after indicator hides
    await Future<void>.delayed(const Duration(seconds: 3));

    if (!isModelExist) {
      showSnackBar();
    }

    return;
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文