1、退出App
SystemNavigator.pop()
2、拦截返回键
WillPopScope(
child: Scaffold(),
onWillPop: () {
/// 如果回调返回一个解析为false的Future,则拦截路由跳转。
/// return Future.value(false);
return Future.value(true);
},
);
3、点击空白取消TextField焦点 隐藏键盘
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
// 点击空白取消所有输入框焦点,隐藏键盘
FocusScope.of(context).requestFocus(FocusNode());
},
child:...,
)
behavior:表现方式。
默认[ HitTestBehavior.deferToChild]
enum HitTestBehavior {
/// 遵从其子女的目标 将在其范围内接收事件,只有当他们的一个孩子被击中时。
/// (child处理事件)
deferToChild,
/// 不透明的目标可以通过命中测试来命中,这使得它们既可以在其范围内接收事件,又可以防止其背后的目标也接收事件。
/// (自己处理事件)
opaque,
/// 半透明目标既可以在其范围内接收事件,也可以允许其背后的可视目标接收事件。
/// (自己和chuild都可以处理事件)
translucent,
}
4、手动移除/获取指定输入框焦点
FocusNode _focusNode = FocusNode();
...
TextField(
focusNode: _focusNode,
...
)
// 移除焦点
_focusNode.unfocus();
// 获得焦点
FocusScope.of(context).requestFocus(_focusNode);
// 是否获得焦点的状态
_focusNode.hasFocus
5、手动弹出/收起键盘
// 手动弹出键盘
SystemChannels.textInput.invokeMethod('TextInput.show');
// 手动收起键盘
SystemChannels.textInput.invokeMethod('TextInput.hide');
6、自定义Widget实现PreferredSize
class CustomPreferredSize extends StatelessWidge implements PreferredSizeWidget {
CustomPreferredSize({
this.height = kToolbarHeight,
this.child,
});
final double height;
final Widget child;
@override
Widget build(BuildContext context) => child;
@override
Size get preferredSize => Size.fromHeight(height);
}
// 使用示例
//Scaffold(
// appBar: CustomPreferredSize(child: _AppBar()),
//);
//class _AppBar extends StatelessWidget {
// @override
// Widget build(BuildContext context) {
// return AppBar(title: Text('DEMO'));
// }
//}
7、dart 千分位格式化金额(正则)
/// 千分位格式化金额
/// [toFixed] 保留多少位小数点 默认保留全部
/// formatMoney(123456) => 123,456
/// formatMoney(123456.1234) => 123,456.1234
/// formatMoney(123456.1234, toFixed: 2) => 123,456.12
static String formatMoney(Object val, {int toFixed}) {
if (toFixed != null) {
val = double.parse(val.toString()).toStringAsFixed(toFixed);
}
List<String> split = val.toString().split('.');
String str = split[0].replaceAll(RegExp(r"\B(?=(\d{3})+(?!\d))"), ",");
if (split.length > 1) return str + '.' + split[1];
return str;
}
8、监测APP前后台切换
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState ();
}
class _DemoState extends State<Demo> with SingleTickerProviderStateMixin, WidgetsBindingObserver {
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
print('切换至前台');
}
super.didChangeAppLifecycleState(state);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
9、重启APP
// 重启APP组件
class ResetApp extends StatefulWidget {
ResetApp({@required this.child});
final Widget child;
static void reset(BuildContext context) async {
//查找顶层_ResetAppState并重启
context.findAncestorStateOfType<_ResetAppState>().reset();
}
@override
_ResetAppState createState() => _ResetAppState();
}
class _ResetAppState extends State<ResetApp> {
Key _key = UniqueKey();
void reset() {
//重新生成key导致控件重新build 达到重启APP的效果
setState(() => _key = UniqueKey());
}
@override
Widget build(BuildContext context) {
return KeyedSubtree(
key: _key,
child: widget.child,
);
}
}
保证ResetApp始终包裹住MaterialApp,如下
void main() {
runApp(
ResetApp(child: MaterialApp()),
);
}
需要重启时调用 ↓
ResetApp.reset(context);
未完待续...