為您解碼網(wǎng)站建設(shè)的點(diǎn)點(diǎn)滴滴
發(fā)表日期:2018-12 文章編輯:小燈 瀏覽次數(shù):2796
Flutter正式版出了,做為一個(gè)Android開發(fā),是時(shí)候跟隨大部隊(duì)進(jìn)坑了。在寫一個(gè)登錄頁(yè)面的時(shí)候登錄是寫完了,突然發(fā)現(xiàn)不知道怎么搞一個(gè)加載中的動(dòng)畫效果,畢竟Android中有ProgressDialog可用,然而Flutter中不知道用啥,那就自己寫一個(gè)出來。
項(xiàng)目地址
先上效果圖:
是不是感覺跟ProgressDialog創(chuàng)建出來的一毛一樣?。?!
首先想到的是用Flutter自帶的SimpleDialog對(duì)話框,但是想到這玩意貌似要主動(dòng)點(diǎn)擊按鈕關(guān)閉,這種方案不符合自己的要求。
在加載的時(shí)候返回加載的布局,不加載的時(shí)候返回登陸頁(yè)面布局,代碼如下:
import 'package:flutter/material.dart'; import 'package:flutter_loading/Toast.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: '加載動(dòng)畫'), ); } }class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key);final String title;@override _MyHomePageState createState() => _MyHomePageState(); }class _MyHomePageState extends State<MyHomePage> { bool _loading = false;@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: _childLayout(), ); }Widget _childLayout() { if (_loading) { return Center( child: Container( child: CircularProgressIndicator(), ), ); } else { return Center( child: RaisedButton( onPressed: () => _onRefresh(), child: Text('顯示加載動(dòng)畫'), ), ); } }Future<Null> _onRefresh() async { setState(() { _loading = !_loading; }); await Future.delayed(Duration(seconds: 3), () { setState(() { _loading = !_loading; Toast.show(context, "加載完成"); }); }); } }
重點(diǎn)在_childLayout()方法,當(dāng)加載中的時(shí)候返回環(huán)形進(jìn)度條,加載完成,返回實(shí)際顯示的布局,代碼效果如下:
GIF0.gif看效果是好像實(shí)現(xiàn),但是這種效果只適合普通數(shù)據(jù)列表頁(yè)面的加載,要是登陸頁(yè)面,你總不能這么搞吧,一點(diǎn)登錄,頁(yè)面布局都跑路了,只有一個(gè)圈圈有啥意思。這種方法也不行。
在原本布局上面疊加一層半透明背景,顯示一個(gè)進(jìn)度條。這個(gè)想法好像可以。重點(diǎn)來了開始擼一波
層疊布局至少有兩個(gè)控件,按照Flutter思想,一切皆控件。我們自定義一個(gè)控件叫ProgressDialog,我們這個(gè)控件接收兩個(gè)必傳參數(shù):子布局child,是否顯示加載進(jìn)度:loading,這兩個(gè)參數(shù)是必須的,所以自定義控件如下
import 'package:flutter/material.dart';class ProgressDialog extends StatelessWidget { final bool loading; final Widget child;ProgressDialog({Key key, @required this.loading, @required this.child}) : assert(child != null), assert(loading != null), super(key: key);@override Widget build(BuildContext context) { return null; } }
構(gòu)造函數(shù)寫好了,那么開始寫控件,Stack層疊布局必須返回兩個(gè)以上的控件,所以先定義一個(gè)List<Widget>,用來放層疊的控件組,首先要把child控件加進(jìn)去,再加一個(gè)加載中的動(dòng)畫。上代碼:
import 'package:flutter/material.dart';class ProgressDialog extends StatelessWidget { final bool loading; final Widget child;ProgressDialog({Key key, @required this.loading, @required this.child}) : assert(child != null), assert(loading != null), super(key: key);@override Widget build(BuildContext context) { List<Widget> widgetList = []; widgetList.add(child); //如果正在加載,則顯示加載添加加載中布局 if (loading) { widgetList.add(Center( child: CircularProgressIndicator(), )); } return Stack( children: widgetList, ); } }
是不是感覺好像很簡(jiǎn)單的樣子,慣例上圖:
加載中1看圖效果好像很接近了,起碼原先的布局沒有被直接替換,但是感覺不美觀,好吧加個(gè)透明背景效果,這里就用到控件Opacity,專門用來繪制透明效果。 上代碼:
import 'package:flutter/material.dart';class ProgressDialog extends StatelessWidget { final bool loading; final Widget child;ProgressDialog({Key key, @required this.loading, @required this.child}) : assert(child != null), assert(loading != null), super(key: key);@override Widget build(BuildContext context) { List<Widget> widgetList = []; widgetList.add(child); //如果正在加載,則顯示加載添加加載中布局 if (loading) { //增加一層黑色背景透明度為0.8 widgetList.add( Opacity( opacity: 0.8, child: ModalBarrier( color: Colors.black87, )), ); //環(huán)形進(jìn)度條 widgetList.add(Center( child: CircularProgressIndicator(), )); } return Stack( children: widgetList, ); } }
老規(guī)矩,上圖:
看著樣子是不是差不多,一般進(jìn)度都可以用了吧,但是如果我要想在進(jìn)度條下方顯示文字怎么辦?并且我看那個(gè)toast樣子蠻好看的,還想要搞成那樣的。好吧,那樣的話加載進(jìn)度條和提示內(nèi)容得是同一層,用個(gè)垂直布局顯示一個(gè)進(jìn)度一個(gè)Text()應(yīng)該能搞定:
import 'package:flutter/material.dart';class ProgressDialog extends StatelessWidget { final bool loading; final Widget child;ProgressDialog({Key key, @required this.loading, @required this.child}) : assert(child != null), assert(loading != null), super(key: key);@override Widget build(BuildContext context) { List<Widget> widgetList = []; widgetList.add(child); //如果正在加載,則顯示加載添加加載中布局 if (loading) { //增加一層黑色背景透明度為0.8 widgetList.add( Opacity( opacity: 0.8, child: ModalBarrier( color: Colors.black87, )), ); //環(huán)形進(jìn)度條 widgetList.add(Center( child: Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( //黑色背景 color: Colors.black87, //圓角邊框 borderRadius: BorderRadius.circular(10.0)), child: Column( //控件里面內(nèi)容主軸負(fù)軸劇中顯示 mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, //主軸高度最小 mainAxisSize: MainAxisSize.min, children: <Widget>[ CircularProgressIndicator(), Text( '加載中...', style: TextStyle(color: Colors.white), ) ], ), ), )); } return Stack( children: widgetList, ); } }
用一個(gè)垂直布局Column包裹進(jìn)度條和提示內(nèi)容,完美解決,已經(jīng)接近目標(biāo)了,圖來-->
增加提醒內(nèi)容.gif目標(biāo)完成,最后潤(rùn)色:提示字體要讓用戶自定義,加載動(dòng)畫也得可以自定義,那么最終代碼如下:
import 'package:flutter/material.dart';class ProgressDialog extends StatelessWidget { //子布局 final Widget child;//加載中是否顯示 final bool loading;//進(jìn)度提醒內(nèi)容 final String msg;//加載中動(dòng)畫 final Widget progress;//背景透明度 final double alpha;//字體顏色 final Color textColor;ProgressDialog( {Key key, @required this.loading, this.msg, this.progress = const CircularProgressIndicator(), this.alpha = 0.6, this.textColor = Colors.white, @required this.child}) : assert(child != null), assert(loading != null), super(key: key);@override Widget build(BuildContext context) { List<Widget> widgetList = []; widgetList.add(child); if (loading) { Widget layoutProgress; if (msg == null) { layoutProgress = Center( child: progress, ); } else { layoutProgress = Center( child: Container( padding: const EdgeInsets.all(20.0), decoration: BoxDecoration( color: Colors.black87, borderRadius: BorderRadius.circular(4.0)), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ progress, Container( padding: const EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0), child: Text( msg, style: TextStyle(color: textColor, fontSize: 16.0), ), ) ], ), ), ); } widgetList.add(Opacity( opacity: alpha, child: new ModalBarrier(color: Colors.black87), )); widgetList.add(layoutProgress); } return Stack( children: widgetList, ); } }
最后附上在工程中調(diào)用的例子代碼:
import 'package:flutter/material.dart'; import 'package:flutter_loading/Toast.dart'; import 'package:flutter_loading/view_loading.dart'; void main() => runApp(MyApp());class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: '加載動(dòng)畫'), ); } }class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key);final String title;@override _MyHomePageState createState() => _MyHomePageState(); }class _MyHomePageState extends State<MyHomePage> { bool _loading = false;@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: ProgressDialog( loading: _loading, msg: '正在加載...', child: Center( child: RaisedButton( onPressed: () => _onRefresh(), child: Text('顯示加載動(dòng)畫'), ), ), ), ); }Future<Null> _onRefresh() async { setState(() { _loading = !_loading; }); await Future.delayed(Duration(seconds: 3), () { setState(() { _loading = !_loading; Toast.show(context, "加載完成"); }); }); } }
對(duì)于加載動(dòng)畫,只要把progress屬性改為自定義的屬性即可,比如這位大佬寫的加載動(dòng)畫:
flutter自定義進(jìn)度動(dòng)畫,我們用他的加載中動(dòng)畫:
只需在上述代碼中加一行(當(dāng)然前提是你得去github上git到他自定義的代碼):
loading: _loading, //自定義動(dòng)畫 progress: MyProgress(size: new Size(100.0, 20.0),color: Colors.white,), msg: '正在加載...',
效果如下:
自定義動(dòng)畫.gif日期:2018-10 瀏覽次數(shù):7268
日期:2018-12 瀏覽次數(shù):4342
日期:2018-07 瀏覽次數(shù):4889
日期:2018-12 瀏覽次數(shù):4186
日期:2018-09 瀏覽次數(shù):5513
日期:2018-12 瀏覽次數(shù):9935
日期:2018-11 瀏覽次數(shù):4821
日期:2018-07 瀏覽次數(shù):4594
日期:2018-05 瀏覽次數(shù):4867
日期:2018-12 瀏覽次數(shù):4334
日期:2018-10 瀏覽次數(shù):5150
日期:2018-12 瀏覽次數(shù):6226
日期:2018-11 瀏覽次數(shù):4478
日期:2018-08 瀏覽次數(shù):4602
日期:2018-11 瀏覽次數(shù):12653
日期:2018-09 瀏覽次數(shù):5593
日期:2018-12 瀏覽次數(shù):4847
日期:2018-10 瀏覽次數(shù):4201
日期:2018-11 瀏覽次數(shù):4540
日期:2018-12 瀏覽次數(shù):6076
日期:2018-06 瀏覽次數(shù):4017
日期:2018-08 瀏覽次數(shù):5449
日期:2018-10 瀏覽次數(shù):4466
日期:2018-12 瀏覽次數(shù):4545
日期:2018-07 瀏覽次數(shù):4370
日期:2018-12 瀏覽次數(shù):4510
日期:2018-06 瀏覽次數(shù):4398
日期:2018-11 瀏覽次數(shù):4385
日期:2018-12 瀏覽次數(shù):4258
日期:2018-12 瀏覽次數(shù):5296
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.