小TIP
这里有个小 Tip ,当代码框里输入 stl 的时候,可以自动弹出创建无状态控件的模板选项,而输入 stf 的时,就会弹出创建有状态 Widget 的模板选项。
代码格式化的时候,括号内外的逗号都会影响格式化时换行的位置。
如果觉得默认换行的线太短,可以在设置-Editor-Code Style-Dart-Wrapping and Braces-Hard wrap at 设置你接受的数值。
NestedScrollView 头部迭代效果
NestedScrollView
带有placeholder的image组件
FadeInImage.assetNetwork(
image: '图片地址',
placeholder: 'images/图片名.png',
fit: BoxFit.cover,//
)
Flutter JSON和序列化
这篇文章里面轻微的介绍
这篇demo可以方便理解点
网络请求库http
网络请求库http
Flutter中如何利用StreamBuilder和BLoC来控制Widget状态
Flutter中如何利用StreamBuilder和BLoC来控制Widget状态
Bloc
Dialog弹出框
Dialog弹出框
不同的widget中获得共同的数据
InheritedWidget
缓存图片和有占位图
缓存图片加载图片等
Flutter底部导航栏NavigationBar的几种实践
Flutter底部导航栏NavigationBar的几种实践
获取tab高度和navbar高度
final double topPadding = MediaQuery.of(context).padding.top;
final double bottomPadding = MediaQuery.of(context).padding.bottom;
上边距在 iPhoneX 上的值是 44, 在其他设备上的值是 20, 是包含了电池条的高度的。
下边距在iPhoneX 上的值是34,在其他设备上的值是 0。
现在Flutter出了一个新的Widget,叫做 SafeArea , 直接在外面包一层这个Widget, 就可以让子Widget 不会被刘海覆盖了
Flutter 布局详解
Flutter 布局详解
遇到这个恶心的问题xcode_backend.sh No such file or directory
/bin/sh: /packages/flutter_tools/bin/xcode_backend.sh: No such file or directory
Issues #17234
跳转动画方式
fullscreenDialog: true
Flutter表单组件
先从最基础的讲起,对于
TextField
就是android中的edittext
,就是一个输入框( TextField class),这个输入框常用的属性如下:
child: new TextField(
autocorrect: false, // 是否自动校正
autofocus: false, //自动获取焦点
enabled: true, // 是否启用
inputFormatters: [], //对输入的文字进行限制和校验
keyboardType: TextInputType.text, //获取焦点时,启用的键盘类型
maxLines: 2, // 输入框最大的显示行数
maxLength: 3, //允许输入的字符长度/
maxLengthEnforced: false, //是否允许输入的字符长度超过限定的字符长度
obscureText: true, // 是否隐藏输入的内容
onChanged: (newValue) {
// print(newValue); // 当输入内容变更时,如何处理
},
onSubmitted: (value) {
// print("whar"); // 当用户确定已经完成编辑时触发
},
style: new TextStyle(
color: new Color(Colors.amberAccent.green)), // 设置字体样式
textAlign: TextAlign.center, //输入的内容在水平方向如何显示
decoration: new InputDecoration(
labelText: "城市",
icon: new Icon(Icons.location_city),
border: new OutlineInputBorder(), // 边框样式
helperText: 'required',
hintText: '请选择你要投保的城市',
prefixIcon: new Icon(Icons.android),
prefixText: 'Hello'),
),
输入处理
其实对于一个输入框,我们最关心的无非就是监听输入的内容,然后输入完成后,输入框中的内容是什么,文档中写的很清楚,textfiled控件有三个回调函数
onChanged事件,在输入内容发生变化的时候触发,onSubmitted事件,则是在输入结束,点击完成的时候触发。
然而在TextFormField中没有这两个事件,取而代之的是validator,onSaved,onFieldSubmitted 他们都接受三个函数,并且将其值作为参数传递到函数里面
validator,如果开启autovalidate: true,那么将会自动检验输入的值,如果没有则会在表单提交的时候检验 该函数只允许返回验证失败的错误信息以及验证通过时返回null。onSaved, 当调用FormState.save方法的时候调用。
onFieldSubmitted, 与onSubmitted一样,则是在输入结束,点击完成的时候触发。
无论是在TextField还是TextFormField中,都有一个重要的属性controller,该属性可用来对输入框内容进行控制。
先创建一个控制对象:
TextEditingController _controller = new TextEditingController();
TextEditingController _formFieldController = new TextEditingController();
//为输入框初始化值以及注册一个监听事件:
@override
void initState() {
// TODO: implement initState
super.initState();
_controller.value = new TextEditingValue(text: 'Hello');
_formFieldController.addListener(() {
print('listener');
});
}
//触发一个监听事件:
void _textFieldAction() {
// print(_formFieldController.selection);
// print(_formFieldController.text); //获取输入内容
print(_formFieldController.hasListeners); //判断是否注册监听事件
_formFieldController.notifyListeners(); //触发监听事件
}
Form
我们使用一个Form包裹着两个TextFormField组件,在这里为了简便,我们只设置了一些必要的元素,
为了获取表单的实例,我们需要设置一个全局类型的key,通过这个key的属性,来获取表单对象。对于表单对象来说,其有一些非常实用的方法比如: reset 重置表单内容 validate, 调用TextFormField的validator方法 save, 表单保存。
import 'package:flutter/material.dart';
void main() => runApp(new HomePage());
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State {
GlobalKey _formKey = new GlobalKey();
String _name;
String _password;
void _forSubmitted() {
var _form = _formKey.currentState;
if (_form.validate()) {
_form.save();
print(_name);
print(_password);
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
title: 'Flutter data',
home: new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Form'),
),
floatingActionButton: new FloatingActionButton(
onPressed: _forSubmitted,
child: new Text('提交'),
),
body: new Container(
padding: const EdgeInsets.all(16.0),
child: new Form(
key: _formKey,
child: new Column(
children: [
new TextFormField(
decoration: new InputDecoration(
labelText: 'Your Name',
),
onSaved: (val) {
_name = val;
},
),
new TextFormField(
decoration: new InputDecoration(
labelText: 'Password',
),
obscureText: true,
validator: (val) {
return val.length < 4 ? "密码长度错误" : null;
},
onSaved: (val) {
_password = val;
},
),
],
),
),
),
),
);
}
}
Flutter Date & Time Pickers 时间选择器
参数 | 说明 |
---|---|
context | - |
initialDate | 初始化时间 |
firstDate | 开始时间,时间控件选择器从这个时间开始 |
lastDate | 结束时间 |
initialDatePickerMode | day:初始化显示天,year:初始化先选择年 |
textDirection | 文本方向 |
import 'package:flutter/material.dart';
class DatePickerDemo extends StatefulWidget {
@override
State createState() => _DatePickerDemo();
}
class _DatePickerDemo extends State {
_showDataPicker() async {
Locale myLocale = Localizations.localeOf(context);
var picker = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2016),
lastDate: DateTime(2019),
locale: myLocale);
setState(() {
_time = picker.toString();
});
}
_showTimePicker() async {
var picker =
await showTimePicker(context: context, initialTime: TimeOfDay.now());
setState(() {
_time = picker.toString();
});
}
var _time;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Column(
children: [
RaisedButton(
child: Text(_time == null ? '选择日期' : _time),
onPressed: () => _showDataPicker(),
),
RaisedButton(
child: Text(_time == null ? '选择时间' : _time),
onPressed: () => _showTimePicker(),
),
],
);
}
}
Issues 'image_picker/ImagePickerPlugin.h' file not found
flutter/plugins#483
I am able to reproduce the error consistently using Cocoapods 1.5.0 (newly released) and freshly created Flutter projects (from Flutter master).
It appears Cocoapods 1.5.0 deals differently with symlinks than some earlier versions, leading to a situation where the Flutter pod is effectively empty inside the Xcode project.
The fix of #16273 appears to solve the problem. You can make this change manually to theios/Podfile
in your existing project, then deleteios/Podfile.lock
andios/Pods/
.
I have tested that the changed Podfiles work with both Cocoapods 1.4.0 and Cocoapods 1.5.0. I have so far been unable to reproduce the issue with the former.
图片如何充满父布局
图片如何充满父布局
- 外面嵌套一层Column(我觉得这种方法有点高射炮打蚊子的感觉。。)
new Column(
children: [
new Image.network(
_parties[index]["cover"], fit: BoxFit.fitWidth,
height: 120.0,
),
new Text(_parties[index]['name'])
]
)
- 直接写上宽和高(前提是你得先知道确切的宽高,比如要全屏显示图片)
Image.asset(
AssetImages.demo,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
fit: BoxFit.cover,
)
- 外面嵌套
BoxConstraints
,给Image
加约束,让它填充父布局。(本人喜欢这种方式)
ConstrainedBox(
child: Image.asset(
AssetImages.start2,
fit: BoxFit.cover,
),
constraints: new BoxConstraints.expand(),
)
圆角图片
- ClipOval
new ClipOval(
child: new Image.asset(Utils.getImgPath('ali_connors')),
)
- CircleAvatar
new CircleAvatar(
radius: 36.0,
backgroundImage: AssetImage(
Utils.getImgPath('ali_connors'),
),
)
- BoxDecoration BoxShape.circle
new Container(
width: 72.0,
height: 72.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage(
Utils.getImgPath('ali_connors'),
),
),
),
)
- ClipRRect
new ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: new Image.asset(Utils.getImgPath('ali_connors')),
)
- BoxDecoration BoxShape.rectangle
new Container(
width: 88.0,
height: 88.0,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(6.0),
image: DecorationImage(
image: AssetImage(
Utils.getImgPath('ali_connors'),
),
),
),