0
点赞
收藏
分享

微信扫一扫

Flutter从零到∞学习笔记

  1. 有状态widget:StatefulWidget和无状态widget:StatelessWidget 前者不需要实现Widget build(BuildContext context)。

    具体的选择取决于widget是否需要管理一些状态

  2. 在Dart语言中使用下划线前缀标识符,会强制其变成私有的。

  3. Icons.favorite Icons类里面有很多默认图标

  4. isOdd 是否奇数 2.isOdd -> false 1.isOdd -> true

  5. pushSaved “”开头的自动转成私有(方法和变量)

  6. 导航栏添加按钮和事件

     @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)
  1. 界面跳转方法
    Navigator.of(context).push(

new MaterialPageRoute(

builder: (context) {

},

),

);
  1. 一行函数写法
    // 多行

void main() {

runApp(

new Center(

child: new Text(

'Hello, world!',

textDirection: TextDirection.ltr,

),

)

)

}

// 一行

void main() => runApp(new MyApp());
  1. // Material 是UI呈现的“一张纸”

  2. 请确保在pubspec.yaml文件中,将flutter的值设置为:uses-material-design: true。这允许我们可以使用一组预定义Material icons。

  3. Row(横向排列)和Column(纵向排列)

    child: new Row(

children: <Widget>[

new ...,

new ...,

new ...,

],

)
    child: new Column(

children: <Widget>[

new ...,

new ...,

new ...,

],

),
  1. cached_network_image 图片占位和淡入淡出

  2. push

    Navigator.push(

context,

new MaterialPageRoute(builder: (context) => new 新界面),

);

// 如果需要传值:

新界面({Key key, @required this.接收字段的名字}) : super(key: key);

pop

Navigator.pop(context);
  1. dio网络请求 https://github.com/flutterchina/dio

  2. import 'dart:convert'; // package将响应内容转化为一个json Map

  3. // 使用fromJson工厂函数,将json Map 转化为一个Post对象

new Post.fromJson(json);
  1. future参数是一个异步的网络请求

  2. import 'dart:io'; // 添加请求的headers

  3. // 长连接

import 'package:web_socket_channel/io.dart';

import 'package:multi_server_socket/multi_server_socket.dart';
  1. // 网络请求
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();

}

)
  1. 长连接
// 连接长连接

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();
  1. 在Flutter中添加资源和图片

https://flutterchina.club/assets-and-images/

  1. 标准widget:
Container

添加 padding, margins, borders, background color, 或将其他装饰添加到widget.

GridView

将 widgets 排列为可滚动的网格.

ListView

将widget排列为可滚动列表

Stack

将widget重叠在另一个widget之上.

Material Components:

Card

将相关内容放到带圆角和投影的盒子中。

ListTile

将最多3行文字,以及可选的行前和和行尾的图标排成一行
  1. 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
  1. 比如一个关闭按钮在
new Row(mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[

new FlatButton(onPressed: () {

}, child: Icon(Icons.close))

],);
  1. 分割线
new Divider(color: Colors.lightBlue,) 
  1. 自定义Icon
new Image.asset(“图片路径", width: 20.0, height: 20.0,)
  1. 按钮宽高
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,

),

);

}
  1. 设备尺寸
MediaQuery.of(context).size.width
  1. 设备像素密度
MediaQuery.of(context).devicePixelRatio
  1. 状态栏高度
MediaQuery.of(context).padding.top
  1. 担心键盘挡住控件,可以使用 SingleChildScrollView,将SingleChildScrollView当做容器。

  2. 一个超级简单界面

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),);

}

}
  1. Flutter 按钮总结
· InkWell   // 纯文字按钮

· OutLineButton // 边框按钮

· IconButton // icon按钮

·
  1. import 'package:flutter/services.dart';
TextField

inputFormatters: <TextInputFormatter> [

WhitelistingTextInputFormatter.digitsOnly,

],
  1. 以上已经添加简书

  2. 验证码按钮

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: () {

},

),

)

),
  1. 倒计时方法
@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();

}
  1. 富文本拼接: 协议
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,

),

)

]

)

),

],

)

);

}
  1. 阴影、圆角
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: () {

}),

)
  1. 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,

),

),

);

}

}
  1. ListView 添加刷新,当数量少的时候不能滚动
physics: new AlwaysScrollableScrollPhysics(), // 让ListView一直可以滚动
  1. tabView切换 子界面都会调用initState
解决:AutomaticKeepAliveClientMixin

class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {

@override

bool get wantKeepAlive => true;

}
  1. 路有跳转
///不带参数的路由表跳转

Navigator.pushNamed(context,routeName);

///跳转新页面并且替换,比如登录页跳转主页

Navigator.pushReplacementNamed(context,routeName);

///跳转到新的路由,并且关闭给定路由的之前的所有页面

Navigator.pushNamedAndRemoveUntil(context,'/calendar',ModalRoute.withName('/'));

///带参数的路由跳转,并且监听返回

Navigator.push(context,newMaterialPageRoute(builder:(context)=>newNotifyPage())).then((res){

///获取返回处理

});
  1. 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';
  1. 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对象

}

}
  1. 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
举报

相关推荐

0 条评论