滚动屏幕自动隐藏软键盘
1
| keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
斜纹背景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Container( width: width, height: height, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment(-0.5, -0.5), stops: [0.0, 0.5, 0.5, 1], colors: [ Colors.grey, Colors.grey, Colors.black45, Colors.black45, ], tileMode: TileMode.repeated, ), ), )
|
baseline

中文会使用TextBaseline.alphabetic对齐,就算设置ideographic,但也无法起效。
1 2 3 4 5 6 7 8 9 10 11
| @override Widget build(BuildContext context) { bool keyboardIsOpened = MediaQuery.of(context).viewInsets.bottom != 0.0; return Scaffold( floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: Visibility( visible: !keyboardIsOpened, child: _floatingActionButton(), ), ); }
|
自动构建
1
| flutter packages pub run build_runner build
|
单个页面修改状态栏文字图标颜色
1 2 3
| AnnotatedRegion<SystemUiOverlayStyle>( value: SystemUiOverlayStyle.light, child: ),
|
Animation<Color>
1
| AlwaysStoppedAnimation<Color>(Colors.white)
|
延迟执行
1 2 3
| await Future.delayed(const Duration(seconds: time), () {
});
|
软键盘覆盖在界面上
1 2
| Scaffold( resizeToAvoidBottomInset: false,)
|
TextField无法顶部对齐
1 2 3 4
| Row( crossAxisAlignment: CrossAxisAlignment.start, textBaseline: TextBaseline.alphabetic, )
|
TextFeild
设置文字后保持光标在文字之后:
1 2 3
| _controller.text = '${Provider.of<PersonState>(context, listen: false).nickName}'; _controller.selection = TextSelection.fromPosition(TextPosition(offset: _controller.text.length));
|
MaterialApp
清除右上角debug角标
1 2
| MaterialApp( debugShowCheckedModeBanner: false,)
|
1 2 3
| Column( children: ['','',''].map((e) => Container()).toList(), ),
|
1 2 3
| Column( children: ['','',''].asMap().map((index,data) => MapEntry(index,Container())).values.toList(), ),
|
List<List>转换成List
1
| List<List<T>>.expand((element)=>element).toList();
|
1 2 3 4
| final _myKey = new GlobalKey(); Scrollable.ensureVisible(_myKey.currentContext, duration: Duration(seconds: 1));
|
弧度和角度换算
1 2 3 4
| num degToRad(num deg) => deg * (pi / 180.0);
num radToDeg(num rad) => rad * (180.0 / pi);
|
对比实例是否相等
可以引入equatable实现
1 2
| import 'package:equatable/equatable.dart'; class Post extends Equatable{}
|
在Flutter中,StatefulWidget只是持有一些immutable(不可变)的数据以及创建它的状态,所有成员变量都应该是final,动态部分全部放到了State中。
当状态改变时,通知视图重新绘制,就是setState。
@immutable 注解
不可修改,只能重新创建。由于const必须在编译时创建,所以有时候需要用immutable来完成不可变。
类一旦创建,成员变量就不可改变。
1 2 3 4 5 6 7
| import 'package:meta/meta.dart';
@immutable class User { final String name; User(this.name) }
|
命令行新建项目
1
| flutter create -i swift -a kotlin 工程名
|
显示布局线
1 2 3 4 5
| import 'package:flutter/rendering.dart' show debugPaintSizeEnabled; void main(){ debugPaintSizeEnabled = true; runApp(new MyApp()); }
|
vsync
当创建一个AnimationController时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画(译者语:动画的UI不在当前屏幕时)消耗不必要的资源。 通过将SingleTickerProviderStateMixin添加到类定义中,可以将stateful对象作为vsync的值。
1
| with SingleTickerProviderStateMixin
|
1
| AnimationController(duration: const Duration(milliseconds: 600), vsync: this);
|
compute
compute是Flutter对dart的lsolate用法的封装。
lsolate类似线程,但相互之间不共享内存。
顶层方法:
1 2 3 4 5 6 7 8
| Future<int> testFunction(String str) async { int result = 0; for (int i = 0; i < 10000000000; i++) { result += i; } return result; }
|
调用:
1 2 3 4
| import 'package:flutter/foundation.dart'; int result = await compute(testFunction,'hello');
|
Row和Column的mainAxisAlignment
- center:将children放置在主轴的中心;
- end:将children放置在主轴的末尾;
- spaceAround:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2;
- spaceBetween:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙;
- spaceEvenly:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child;
- start:将children放置在主轴的起点;
BoxFit
- BoxFit.none:原始大小。超过就截取中间,不足就两边留空。
- BoxFit.fill:拉伸占满。
- BoxFit.contain:等比缩放。
- BoxFit.cover:截取中间
- BoxFit.fitWidth:宽度占满。上下可能留空也可能截取。
- BoxFit.fitHeight:高度占满。左右可能留空也可能截取。
- BoxFit.scaleDown:大于父控件,则采用与contain一致的缩放模式,否则采用none缩放模式。
圆角框
1 2 3 4
| decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(6.0)), ),
|
Slivers家族
- SliverAppBar:可折叠的AppBar。
- SliverList:list列表。
- SliverFixedExtentList:每项高度固定的list列表。
- SliverToBoxAdapter:有明确尺寸的child。
- SliverPadding:包含其他sliver并提供padding。
- SliverGrid:GridView。
保留2位小数
1
| double.toStringAsFixed(2)
|
TextField控制字符数但去掉右下角记数
1
| decoration: InputDecoration(counterText: '',),
|
Timer定时执行,非阻塞
1 2 3 4
| import 'dart:async'; new Timer(new Duration(milliseconds: 2000), () { });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Timer _timer; @override void dispose() { _timer.cancel(); super.dispose(); }
void _startTimer() { timerNumber = 60; const oneSec = const Duration(seconds: 1); _timer = new Timer.periodic(oneSec, (Timer timer) { setState(() { if (timerNumber < 1) { timer.cancel(); timerNumber = 60; } else { timerNumber = timerNumber - 1; } }); }); }
|
Future.delayed,延时执行
阻塞,可以用在Future方法中
1 2 3 4
| Future< Null > getData() async { await Future.delayed(Duration(milliseconds: 3000),(){ }); }
|
某个页面或某个控件使用自己的主题
1 2 3 4
| Theme( data: ThemeData( dialogBackgroundColor: Colors.white54, ),),
|
连续点击2次才能退出应用
使用WillPopScope包裹,拦截返回按键
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| DateTime _lastPressedAt; return WillPopScope( onWillPop: () async { if (_lastPressedAt == null || DateTime.now().difference(_lastPressedAt) > Duration(seconds: 1)) { Fluttertoast.showToast( fontSize: 14.0, msg: "再按一次退出程序", toastLength: Toast.LENGTH_SHORT, timeInSecForIos: 1, textColor: Colors.white, gravity: ToastGravity.BOTTOM, ); _lastPressedAt = DateTime.now(); return false; } return true; }, child:... );
|
1 2 3 4
| bool notNull(Object o) => o != null; children: <Widget>[ null, ].where(notNull).toList(),
|
初始化UI后执行
1 2 3 4 5 6 7
| @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_){ }); }
|
1 2 3 4
| OutlineInputBorder( borderSide: BorderSide(color: Theme.of(context).primaryColor ), borderRadius: BorderRadius.circular(8.0), ),
|