有狀態widget:StatefulWidget和無狀態widget:StatelessWidget 前者不須要實現Widget build(BuildContext context)。css
具體的選擇取決於widget是否須要管理一些狀態python
在Dart語言中使用下劃線前綴標識符,會強制其變成私有的。git
Icons.favorite Icons類裏面有不少默認圖標github
isOdd 是否奇數 2.isOdd -> false 1.isOdd -> trueweb
pushSaved 「」開頭的自動轉成私有(方法和變量)json
導航欄添加按鈕和事件api
@override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('Startup Name Generator'), actions: <Widget>[ // AppBar 添加一個按鈕 樣式爲list 事件是_pushSaved new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved) ], ), body: _buildSuggestions(), ); } // tooltip 長時間按下的提示文字 IconButton(icon: new Icon(Icons.search), tooltip: 'Search', onPressed: null)
Navigator.of(context).push( new MaterialPageRoute( builder: (context) { }, ), );
// 多行 void main() { runApp( new Center( child: new Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ) ) } // 一行 void main() => runApp(new MyApp());
// Material 是UI呈現的「一張紙」websocket
請確保在pubspec.yaml文件中,將flutter的值設置爲:uses-material-design: true。這容許咱們可使用一組預約義Material icons。網絡
Row(橫向排列)和Column(縱向排列)app
child: new Row( children: <Widget>[ new ..., new ..., new ..., ], )
child: new Column( children: <Widget>[ new ..., new ..., new ..., ], ),
cached_network_image 圖片佔位和淡入淡出
push
Navigator.push( context, new MaterialPageRoute(builder: (context) => new 新界面), ); // 若是須要傳值: 新界面({Key key, @required this.接收字段的名字}) : super(key: key); pop Navigator.pop(context);
import 'dart:convert'; // package將響應內容轉化爲一個json Map
// 使用fromJson工廠函數,將json Map 轉化爲一個Post對象
new Post.fromJson(json);
future參數是一個異步的網絡請求
import 'dart:io'; // 添加請求的headers
// 長鏈接
import 'package:web_socket_channel/io.dart'; import 'package:multi_server_socket/multi_server_socket.dart';
Future<Post> fetchPost() async { final response = await http.get('[http://jsonplaceholder.typicode.com/posts/1](http://jsonplaceholder.typicode.com/posts/1)'); final responseJson = json.decode(response.body); return new Post.fromJson(responseJson); } // 請求添加headers /* Future<Post> fetchPost() async { final response = await http.get( '[https://jsonplaceholder.typicode.com/posts/1](https://jsonplaceholder.typicode.com/posts/1)', headers: {HttpHeaders.AUTHORIZATION: "Basic your_api_token_here"}, ); final json = jsonDecode(response.body); return new Post.fromJson(json); } */ new FutureBuilder<Post>( future: fetchPost(), builder: (context, snapshot) { return new CircularProgressIndicator(); } )
// 鏈接長鏈接 IOWebSocketChannel.connect('[ws://echo](ws://echo/).[websocket.org](http://websocket.org/)’) // 接收消息 new StreamBuilder( stream: widget.channel.stream, builder: (context, snapshot) { return new Padding( child: new Text(snapshot.hasData ? '${snapshot.data}' : ''), padding: const EdgeInsets.symmetric(vertical: 20.0) ); } ) // 發送消息 widget.channel.sink.add(_textController.text); // 關閉長鏈接 widget.channel.sink.close();
https://flutterchina.club/assets-and-images/
Container 添加 padding, margins, borders, background color, 或將其餘裝飾添加到widget. GridView 將 widgets 排列爲可滾動的網格. ListView 將widget排列爲可滾動列表 Stack 將widget重疊在另外一個widget之上. Material Components: Card 將相關內容放到帶圓角和投影的盒子中。 ListTile 將最多3行文字,以及可選的行前和和行尾的圖標排成一行
-asset 路徑是與pubspec.yaml平級的文件路徑 flutter: # Include the Material Design fonts. uses-material-design: true fonts: - family: Rock Salt fonts: # [https://fonts.google.com/specimen/Rock+Salt](https://fonts.google.com/specimen/Rock+Salt) - asset: fonts/Arial-Unicode.ttf - family: VT323 fonts: # [https://fonts.google.com/specimen/VT323](https://fonts.google.com/specimen/VT323) - asset: fonts/Arial-Unicode.ttf - family: Ewert fonts: # [https://fonts.google.com/specimen/Ewert](https://fonts.google.com/specimen/Ewert) - asset: fonts/Ewert-Regular.ttf
new Row(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ new FlatButton(onPressed: () { }, child: Icon(Icons.close)) ],);
new Divider(color: Colors.lightBlue,)
new Image.asset(「圖片路徑", width: 20.0, height: 20.0,)
00一、 new Padding(padding: new EdgeInsets.fromLTRB(48.0, 20.0, 48.0, 20.0), child: new Row( children: <Widget>[ new Expanded(child: new RaisedButton(onPressed: (){ }, //設置控件的高度 child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: new Text("登陸", style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ), ), ], ), ), 00二、 new Container( width: MediaQuery.of(context).size.width - 48 * 2 , padding: new EdgeInsets.only(top: 40.0), child: new RaisedButton(onPressed: (){ }, //設置控件的高度 child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), child: new Text("登陸", style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ), ), 00三、 Widget _bigButton(String text, double lSpace, double rSpace) { return new Container( width: MediaQuery.of(context).size.width - lSpace - rSpace, height: 48.0, margin: new EdgeInsets.only(left: lSpace, right: rSpace), color: Colors.white54, padding: new EdgeInsets.only(top: 0.0), child: new RaisedButton(onPressed: (){ print(text); }, child: new Padding(padding: new EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0), child: new Text(text, style: TextStyle(color: Colors.white) ), ), color: Colors.brown, ), ); }
MediaQuery.of(context).size.width
MediaQuery.of(context).devicePixelRatio
MediaQuery.of(context).padding.top
擔憂鍵盤擋住控件,可使用 SingleChildScrollView,將SingleChildScrollView當作容器。
一個超級簡單界面
import 'package:flutter/material.dart'; class RegisterPage extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( backgroundColor: Colors.black, body: new RegisterWidget(), ); } } class RegisterWidget extends StatefulWidget { RegisterWidgetState createState() => RegisterWidgetState(); } class RegisterWidgetState extends State<RegisterWidget> { @override Widget build(BuildContext context) { return new Text("RegisterPage", style: TextStyle(color: Colors.white),); } }
· InkWell // 純文字按鈕 · OutLineButton // 邊框按鈕 · IconButton // icon按鈕 ·
TextField inputFormatters: <TextInputFormatter> [ WhitelistingTextInputFormatter.digitsOnly, ],
37 . 驗證碼按鈕
new Positioned( child: new Container( width: 80.0, height: 27.0, alignment: Alignment.center, decoration: new BoxDecoration( border: new Border.all( color: Colors.white, width: 1.0, ), borderRadius: new BorderRadius.circular(4.0), ), child: InkWell( child: _mText(_verifyStr, 12.0), onTap: () { }, ), ) ),
@override void dispose() { super.dispose(); _cancelTimer(); } _startTimer() { if (_verifyStr == '從新發送' || _verifyStr == '獲取驗證碼') { _seconds = 5; _timer = new Timer.periodic(new Duration(seconds: 1), (timer) { if (_seconds == 0) { _cancelTimer(); return; } _seconds--; _verifyStr = '$_seconds(s)'; setState(() {}); if (_seconds == 0) { _verifyStr = '從新發送'; } }); } } _cancelTimer() { _timer?.cancel(); }
Widget _protocolWidget() { return new Container( child: new Row( children: <Widget>[ new GestureDetector( onTap: () { print("選擇"); }, child: Icon(Icons.add_alert, color: Colors.white), ), new Text.rich( new TextSpan( text: '我已閱讀並贊成', style: new TextStyle( fontSize: 12.0, color: Colors.grey[500], fontWeight: FontWeight.w400, ), children: [ new TextSpan( recognizer: new TapGestureRecognizer() ..onTap = () { print("《燎原用戶服務協議》"); }, text: "《燎原用戶服務協議》", style: new TextStyle( fontSize: 14.0, color: Color(0XFFB57A36), fontWeight: FontWeight.w400, ), ) ] ) ), ], ) ); }
new Card( elevation: 4.0, shape: new RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), bottomLeft: Radius.circular(12.0), bottomRight: Radius.circular(2.0), ) ), child: new IconButton(icon: Icon(Icons.add), onPressed: () { }), )
import 'package:flutter/material.dart'; // with AutomaticKeepAliveClientMixin class YYTabbarWidget extends StatefulWidget { List<Widget> tabItems = []; Widget title; List<Widget> tabViews = []; PageController pageController; final ValueChanged<int> onPageChanged; final Widget drawer; YYTabbarWidget({Key key, this.drawer, this.tabItems, this.title, this.tabViews, this.pageController, this.onPageChanged, }) : super(key: key); _YYTabbarWidgetState createState() => _YYTabbarWidgetState(drawer, title, tabItems, tabViews, pageController, onPageChanged); } class _YYTabbarWidgetState extends State<YYTabbarWidget> with SingleTickerProviderStateMixin { final Widget _title; final List<Widget> _tabViews; final List<Widget> _tabItems; final ValueChanged<int> _onPageChanged; final Widget _drawer; _YYTabbarWidgetState( this._drawer, this._title, this._tabItems, this._tabViews, this._pageController, this._onPageChanged, ) : super(); TabController _tabController; PageController _pageController; @override void initState() { super.initState(); _tabController = new TabController(length: _tabItems.length, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } _renderTab() { print(_tabItems); List<Widget> list = new List(); for (int i = 0; i < _tabItems.length; i++) { list.add(new FlatButton(onPressed: () { print(i); _pageController.jumpTo(MediaQuery .of(context) .size .width * i); }, child: _tabItems[I], ) ); } return list; } @override Widget build(BuildContext context) { return new Scaffold( drawer: _drawer, appBar: new AppBar( title: _title, ), body: new PageView( controller: _pageController, children: _tabViews, onPageChanged: (index) { _tabController.animateTo(index); _onPageChanged?.call(index); }, ), bottomNavigationBar: new Material( color: Colors.white, child: new TabBar( indicatorPadding: new EdgeInsets.only(top: 0.0), controller: _tabController, tabs: _renderTab(), indicatorColor: Colors.red, ), ), ); } }
physics: new AlwaysScrollableScrollPhysics(), // 讓ListView一直能夠滾動
解決:AutomaticKeepAliveClientMixin class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; }
///不帶參數的路由表跳轉 Navigator.pushNamed(context,routeName); ///跳轉新頁面而且替換,好比登陸頁跳轉主頁 Navigator.pushReplacementNamed(context,routeName); ///跳轉到新的路由,而且關閉給定路由的以前的全部頁面 Navigator.pushNamedAndRemoveUntil(context,'/calendar',ModalRoute.withName('/')); ///帶參數的路由跳轉,而且監聽返回 Navigator.push(context,newMaterialPageRoute(builder:(context)=>newNotifyPage())).then((res){ ///獲取返回處理 });
cupertino_icons: ^0.1.2 #icon flutter_spinkit: "^2.1.0" # load more loading import 'package:flutter_spinkit/flutter_spinkit.dart'; dio: x.x.x #無網絡請求 import 'package:dio/dio.dart';
_dioRequest() async { Dio dio = new Dio(); Response response; try { String url; var params; // 請求參數 Options options; // 配置:超時,請求頭,請求類型等 response = await dio.request(url, data: params, options: options); } on DioError catch(e) { // 請求出錯時,返回一個DioError對象 } }
一、在根目錄運行 二、一次性建立.g.dart文件 使用build 此時目錄內不能有.g.dart文件 三、watch是監聽 有model類的文件建立 自動建立.g.dart文件 flutter packages pub run build_runner build flutter packages pub run build_runner watch