### 上拉加載下拉刷新 ``` import 'dart:async'; import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:flutter_easyrefresh/bezier_hour_glass_header.dart'; import 'package:flutter_easyrefresh/bezier_bounce_footer.dart'; import 'package:flutter_smart_park/widget/refresh/emptyWidget.dart'; List list = []; GlobalKey<EasyRefreshState> _easyRefreshKey = new GlobalKey<EasyRefreshState>(); GlobalKey<RefreshHeaderState> _headerKey = new GlobalKey<RefreshHeaderState>(); GlobalKey<RefreshFooterState> _footerKey = new GlobalKey<RefreshFooterState>(); new EasyRefresh( key: _easyRefreshKey, autoLoad: true, //自動加載 autoControl: false, //自動控制 firstRefresh: true, //首次加載 firstRefreshWidget: null, refreshHeader: BezierHourGlassHeader( key: _headerKey, color: Theme.of(context).scaffoldBackgroundColor, ), refreshFooter: BezierBounceFooter( key: _footerKey, color: Theme.of(context).scaffoldBackgroundColor, ), child: new text('data'), emptyWidget: new EmptyWidget(), onRefresh: () async { List a = []; for (var i = 0; i < 10; i++) { a.add(i); } new Timer(new Duration(seconds: 2), () { setState(() { list.clear(); list.addAll(a); }); _easyRefreshKey.currentState.callRefreshFinish(); }); }, loadMore: () async { List a = []; for (var i = 0; i < 10; i++) { a.add(i); } new Timer(new Duration(seconds: 2), () { setState(() { if (list.length < 20) { list.addAll(a); print(list.length); } }); _easyRefreshKey.currentState.callLoadMoreFinish(); }); }, ), ``` ### 底部導航 ``` bottomNavigationBar: BottomNavigationBar( items: <BottomNavigationBarItem>[ BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')), BottomNavigationBarItem(icon: Icon(Icons.business), title: Text('Business')), BottomNavigationBarItem(icon: Icon(Icons.school), title: Text('School')), ], currentIndex: _selectedIndex, fixedColor: Colors.deepPurple, onTap: _onItemTapped, ), ``` ### listView 列表 ``` new ListView.builder( scrollDirection: Axis.horizontal, //橫向 shrinkWrap:true, // 自動高度 physics: NeverScrollableScrollPhysics(), // 禁止滾動 itemCount: 10, itemBuilder: (BuildContext context, int index) { }, ), ``` ### text 文本 ``` Text( "Hello world "*6, //字符串重復六次 textAlign: TextAlign.center, //對齊方式 overflow: TextOverflow.ellipsis, // 文本溢出 maxLines: 3, // 最多顯示的行數 textScaleFactor: 1.5, style: TextStyle( color: Colors.blue, fontSize: 18.0, height: 1.2, fontFamily: "Courier", background: new Paint()..color=Colors.yellow, decoration:TextDecoration.underline, decorationStyle: TextDecorationStyle.dashed ), ); // 一行文字多種樣式 Text.rich( TextSpan( children: [ TextSpan( text: "Home: " ), TextSpan( text: "https://flutterchina.club", style: TextStyle( color: Colors.blue ), ), ] ), ) ``` ### Container容器 ``` new Container( alignment: Alignment.center, //對齊方式 decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.lightBlue, Colors.greenAccent, Colors.purple], begin: FractionalOffset(0, 0), end: FractionalOffset(1, 1), ), border: Border.all( width: 2.0, color: Colors.red, ), image: DecorationImage( // 背景圖片 image: AssetImage('assets/images/parkingbg.png'), //本地 centerSlice: Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0), ), ), ), ``` ### Image圖片 BoxFit.fill:全圖顯示,圖片會被拉伸,並充滿父容器。 BoxFit.contain:全圖顯示,顯示原比例,可能會有空隙。 BoxFit.cover:顯示可能拉伸,可能裁切,充滿(圖片要充滿整個容器,還不變形)。 BoxFit.fitWidth:寬度充滿(橫向充滿),顯示可能拉伸,可能裁切。 BoxFit.fitHeight :高度充滿(豎向充滿),顯示可能拉伸,可能裁切。 BoxFit.scaleDown:效果和contain差不多,但是此屬性不允許顯示超過源圖片大小,可小不可大。 ImageRepeat.repeat : 橫向和縱向都進行重復,直到鋪滿整個畫布。 ImageRepeat.repeatX: 橫向重復,縱向不重復。 ImageRepeat.repeatY:縱向重復,橫向不重復。 ``` new Image.network( 'http://jspang.com/static/myimg/blogtouxiang.jpg', scale:1.0, fit:BoxFit.cover, olorBlendMode: BlendMode.darken, //圖片混合模式 repeat: ImageRepeat.repeat, //圖片重復 ), CachedNetworkImage( imageUrl: 'https://pro.modao.cc/uploads4/images/3089/30894737/v2_pnb2pb.png', placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Icon(Icons.error), fit: BoxFit.cover, width: ScreenUtil().setWidth(130), height: ScreenUtil().setWidth(90), ), ``` ### GridView網格列表組件 ``` new GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 2.0, crossAxisSpacing: 2.0, childAspectRatio: 0.7 ), children: <Widget>[ new Image.network('http://img5.mtime.cn/mt/2018/10/22/104316.77318635_180X260X4.jpg',fit: BoxFit.cover), new Image.network('http://img5.mtime.cn/mt/2018/10/10/112514.30587089_180X260X4.jpg',fit: BoxFit.cover), ], ) new GridView.builder( shrinkWrap: true, physics: new NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, //一行多少列 mainAxisSpacing: ScreenUtil().setWidth(LqruiStyle.borderWidth), //y軸距離 crossAxisSpacing: ScreenUtil().setWidth(LqruiStyle.borderWidth), //x軸距離 childAspectRatio: 1.4, //框的比列 ), itemCount: homeIcon.length, itemBuilder: (BuildContext context, int index) { <!-- 內容 --> }, ), ``` ### Column垂直布局 ``` new Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('I am JSPang'), Text('my website is jspang.com'), Text('I love coding') ], ) ``` ### Row橫向布局 ``` new Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Expanded( child: Text('I am JSPang'), ) Text('my website is jspang.com'), Text('I love coding') ], ) ``` ### Stack層疊布局 ``` var stack = new Stack( alignment: const FractionalOffset(0.5, 0.8), children: <Widget>[ new CircleAvatar( backgroundImage: new NetworkImage('http://jspang.com/static//myimg/blogtouxiang.jpg'), radius: 100.0, ), new Container( decoration: new BoxDecoration( color: Colors.lightBlue, ), padding: EdgeInsets.all(5.0), child: new Text('JSPang 技術胖'), ), new Positioned( bottom:10.0, right:10.0, child: new Text('技術胖'), ), ], ); ``` ### Card卡片組件布局 ``` new Card( child: Column( children: <Widget>[ ListTile( title:new Text('吉林省吉林市昌邑區',style: TextStyle(fontWeight: FontWeight.w500),), subtitle: new Text('技術胖:1513938888'), leading: new Icon(Icons.account_box,color: Colors.lightBlue,), ), new Divider(), ListTile( title:new Text('北京市海淀區中國科技大學',style: TextStyle(fontWeight: FontWeight.w500),), subtitle: new Text('勝宏宇:1513938888'), leading: new Icon(Icons.account_box,color: Colors.lightBlue,), ), new Divider(), ListTile( title:new Text('河南省濮陽市百姓辦公樓',style: TextStyle(fontWeight: FontWeight.w500),), subtitle: new Text('JSPang:1513938888'), leading: new Icon(Icons.account_box,color: Colors.lightBlue,), ), new Divider(), ], ), ); ``` ### 路由 ``` import 'package:fluro/fluro.dart'; import 'package:flutter_smart_park/routes/routes.dart'; Routes.router .navigateTo(context, '${Routes.xxx}?id=1', transition: TransitionType.inFromRight) .then((result) { print(result); }); Routes.router.navigateTo( context, '${Routes.userSignUp}', transition: TransitionType.inFromRight, ); Navigator.of(context).pop(); ``` ### 文本左右布局 ``` Widget page(title, text) { return new Container( margin: EdgeInsets.only(top: ScreenUtil().setWidth(10)), child: Row( children: <Widget>[ Expanded( child: Text( '$title', style: TextStyle( color: Color(LqruiStyle.colorText2), fontSize: ScreenUtil().setSp(14), ), ), ), Expanded( flex: 0, child: Text( '$text', style: TextStyle( fontSize: ScreenUtil().setSp(14), ), ), ), ], ), ); } ``` ### 文本默認樣式 ``` new DefaultTextStyle( //1.設置文本默認樣式 style: TextStyle( color:Colors.red, fontSize: 20.0, ), textAlign: TextAlign.start, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text("hello world"), Text("I am Jack"), Text("I am Jack", style: TextStyle( inherit: false, //2.不繼承默認樣式 color: Colors.grey ), ), ], ), ); ``` ### 頁面加載事件 ``` @override void initState() { super.initState(); print('111111111111111111111111111'); } ``` ### 輸入法彈起導致容器越界 ``` 1. 包一層SingleChildScrollView 2. 設置Scaffold resizeToAvoidBottomPadding: false, ``` ### 切換后頁面狀態的保持 ``` // 子頁面 class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive =>true; } // 使用 IndexedStack new IndexedStack( index: currentIndex, children: tabBodies ) ``` ### 點擊事件 ``` new GestureDetector( child: new Text("忘記密碼"), onTap: () => {}, //點擊 onDoubleTap: () => {}, //雙擊 onLongPress: () => {}, //長按 ), ``` ### 輸入框 ``` Container( child: TextField( keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: "Email", hintText: "電子郵件地址", prefixIcon: Icon(Icons.email), border: InputBorder.none //隱藏下划線 ) ), decoration: BoxDecoration( // 下滑線淺灰色,寬度1像素 border: Border(bottom: BorderSide(color: Colors.grey[200], width: 1.0)) ), ) Theme( data: Theme.of(context).copyWith( hintColor: Color(LqruiStyle.dividerColor), //定義下划線顏色 inputDecorationTheme: InputDecorationTheme( labelStyle: TextStyle(color: Colors.grey), //定義label字體樣式 hintStyle: TextStyle( color: Colors.grey, fontSize: 14.0) //定義提示文本樣式 ), ), child: Form(), ), ``` ### 圓角容器 ``` new ClipOval( //默認全圓角 child: Container( width: 100, height: 100, color: Colors.red, ), ), new ClipRRect( //自定義 borderRadius: BorderRadius.circular(50) child: Container( width: 100, height: 100, color: Colors.red, ), ), // shape屬性 new Container( width: 72.0, height: 72.0, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: AssetImage( Utils.getImgPath('ali_connors'), ), ), ), ) ``` ### 下拉框 ``` DropdownButtonHideUnderline( //隱藏下划線盒子 child: DropdownButton( items: items, //下拉菜單item點擊之后的回調 hint: new Text('下拉選擇你想要的數據'), //當沒有默認值的時候可以設置的提示 value: widget.select, //下拉菜單選擇完之后顯示給用戶的值 onChanged: widget.onChanged, //下拉菜單item點擊之后的回調 elevation: 24, //設置陰影的高度 // isDense: true, //減少按鈕的高度。默認情況下,此按鈕的高度與其菜單項的高度相同。如果isDense為true, 則按鈕的高度減少約一半。 這個當按鈕嵌入添加的容器中時,非常有用 isExpanded: true, iconSize: ScreenUtil().setSp(30), //設置三角標icon的大小 ), ); ``` ### 單邊框 ``` decoration: BoxDecoration( border: Border( left: BorderSide( width: ScreenUtil().setWidth(5), color: Color(LqruiStyle.primaryColor), style: BorderStyle.solid, ), ), ), ``` ### 模擬器分辨率 ``` 414 736 154 360 640 160 ``` ### 狀態欄去陰影 ``` import 'dart:io'; import 'package:flutter/services.dart'; if (Platform.isAndroid) { SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle( statusBarColor: Colors.red, ); SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); } appBar中 elevation: 0, ``` ### 接收參數 ``` final id; final title; ApplyReim({Key key, @required this.id, this.title}) : super(key: key); ``` ### 子組件傳參 => 父組件 ``` // 父組件 var data; void onDataChange(val) { setState(() { data = val; }); } @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ChildTwo(data4Two: data4Two, callback: (val) => onDataChange(val)), // 子組件 Container( child: Column( children: <Widget>[ Text('子組件2, 傳過來的值: ' + '$data'), ] ), ) ], ), ); } // 子組件接收callback,並在某事件中觸發 widget.callback(...要返回的數據...); PhotoDetail({Key key, @required this.list, this.index}) : super(key: key); ``` ### 監聽Widget寬/高 ``` import 'package:flustars/flustars.dart'; double cardHeight; Builder( builder: (BuildContext context) { WidgetUtil widgetUtil = new WidgetUtil(); widgetUtil.asyncPrepare(context, true, (Rect rect) { Rect rect = WidgetUtil.getWidgetBounds(context); setState(() { cardHeight = rect.height.toInt(); }); }); return ...; } ) ``` ### 進度條 ``` LinearProgressIndicator( backgroundColor: Color(0x42000000), value: 10 / 30, // value值為null時為一個動畫 valueColor: AlwaysStoppedAnimation<Color>(Colors.white), ), ```
### Text屬性詳解