Flutter: показ прелоадера при загрузке данных в виджете showDialog
Задача: при отображении данных при помощи виджета showDialog, необходимо показывать «прелоадер» во время загрузки данных со стороннего ресурса.
Решение: для отображения прелоадера, используем пакет card_loader. Однако! дело осложняется тем, что виджет showDialog не имеет метода setState, соответственно у нас нет возможности изменить уже отображенные данные, после окончания загрузки.
Для обхода этого ограничения, оформим showDialog как полноценный StatefulWidget с получением в связи с этим стандартных плюшек в виде setState, а так-же возможность вызова своих процедур после окончания отображения виджета:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import 'package:flutter/material.dart'; import 'package:card_loading/card_loading.dart'; import 'dart:convert'; class MyMeDialogInfo extends StatefulWidget { @override State<StatefulWidget> createState() { return _MyMeDialogInfoState(); } } class _MyMeDialogInfoState extends State<MyMeDialogInfo> { bool info_is_load=false; void RefreshMeDialogData(context){ TRequests req=new TRequests(); req.request("adfserfserf", {}), (List result){ setState(() { //info_is_load=true; }); }, (String error){ }); } @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => RefreshMeDialogData(context)); // эвент после того как страница отобразилась - обновим данные по пользователю } @override Widget build(BuildContext context) { return Align ( alignment: Alignment.bottomCenter, child: Container( width: double.infinity, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(32.0), topRight: Radius.circular(32.0))), child:Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // заголовок окна Padding( padding: const EdgeInsets.all(16.0), child: Material( child: Text("Заголовок окна", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0, color: Colors.black))), ), Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height - 220, decoration: BoxDecoration(), child: SingleChildScrollView( child: Stack( children: <Widget>[ Visibility( visible: info_is_load, child: Padding( padding: const EdgeInsets.all(16.0), child: Material( child: Text("Тут перечисляем какую инфу загружаемую асинхронно", style: TextStyle(fontSize: 14.0, color: Colors.black))), ) ), Visibility( visible: !info_is_load, child: Padding( padding: const EdgeInsets.only(bottom: 20,left: 20,right: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: const [ CardLoading( height: 30, borderRadius: BorderRadius.all(Radius.circular(15)), width: 100, margin: EdgeInsets.only(bottom: 10), ), CardLoading( height: 100, borderRadius: BorderRadius.all(Radius.circular(15)), margin: EdgeInsets.only(bottom: 10), ), CardLoading( height: 30, width: 200, borderRadius: BorderRadius.all(Radius.circular(15)), margin: EdgeInsets.only(bottom: 10), ), ], ), ) ) ], ), ), ) ] ) ) ); } } class TMeDialog { void MeDialogInfoDialog(BuildContext context,Map ezs){ showDialog( context: context, builder: (BuildContext context) { return MyMeDialogInfo(ezs); }, ); } } |