-
有状态widget:StatefulWidget和无状态widget:StatelessWidget 前者不需要实现Widget build(BuildContext context)。
具体的选择取决于widget是否需要管理一些状态
在Dart语言中使用下划线前缀标识符,会强制其变成私有的。
Icons.favorite Icons类里面有很多默认图标
isOdd 是否奇数 2.isOdd -> false 1.isOdd -> true
pushSaved “”开头的自动转成私有(方法和变量)
导航栏添加按钮和事件
@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呈现的“一张纸”
请确保在pubspec.yaml文件中,将flutter的值设置为:uses-material-design: true。这允许我们可以使用一组预定义Material icons。
Row(横向排列)和Column(纵向排列)
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();
- 在Flutter中添加资源和图片
https://flutterchina.club/assets-and-images/
- 标准widget:
Container 添加 padding, margins, borders, background color, 或将其他装饰添加到widget. GridView 将 widgets 排列为可滚动的网格. ListView 将widget排列为可滚动列表 Stack 将widget重叠在另一个widget之上. Material Components: Card 将相关内容放到带圆角和投影的盒子中。 ListTile 将最多3行文字,以及可选的行前和和行尾的图标排成一行
- pubspec.yaml中添加字体 注意缩进对齐 注意缩进对齐 注意缩进对齐
-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,)
- 自定义Icon
new Image.asset(“图片路径", width: 20.0, height: 20.0,)
- 按钮宽高
001、 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, ), ), ], ), ), 002、 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, ), ), 003、 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),); } }
- Flutter 按钮总结
· InkWell // 纯文字按钮 · OutLineButton // 边框按钮 · IconButton // icon按钮 ·
- import 'package:flutter/services.dart';
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: () { }), )
- YYTabbarWidget
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, ), ), ); } }
- ListView 添加刷新,当数量少的时候不能滚动
physics: new AlwaysScrollableScrollPhysics(), // 让ListView一直可以滚动
- tabView切换 子界面都会调用initState
解决: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){ ///获取返回处理 });
- flutter lib
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';
- dio网络请求示例
_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对象 } }
- build_runner的使用
1、在根目录运行 2、一次性创建.g.dart文件 使用build 此时目录内不能有.g.dart文件 3、watch是监听 有model类的文件创建 自动创建.g.dart文件 flutter packages pub run build_runner build flutter packages pub run build_runner watch