Flutter widgets
stateful widgets
stateful widget 中可以通过传入的data(external data)参数重新渲染组件, 同时在组件内部改变数据(internal data)
class MyApp extends StatefulWidget {
final String text;
MyApp(this.text); // constructor
State<StatefulWidget> createstate(){
return _myapp()
}
}
class _myapp extends State<MyApp>{
List<String> texts = [];
void iniState() {
super.initState();
this.texts.add(Widget.text);
}// Widget
Widget build(BuildContext context) {
return //return something
...
onPressed(
setState() {
//do something
}
)
}
}
stateless widget
stateless widget 用于渲染普通组件, 静态组件
class Product extends StatelessWidget {
final List<String> products;
Product(this.products);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Column(
children: products
.map(
(element) => Card(
elevation: 6.0,
child: Column(
children: <Widget>[
Image.asset('assets/food.jpg'),
Text(element)
],
),
), //card
)
.toList(),
);
}
}
Create ListView
用来创建一个dynamic list
使用 ListView.builder
Widget build(BuildContext context){
return ListView.builder(
itemBuilder: ,// how to create a widget
itemCount: // how many times
)
}
假设我们定义了一个List<String>
itemCount 就是长度: products.length
itembuilder 对应了一个widget 带两个参数:
widget pattern(BuildContext context, int index) {
return Card(
child: Column(
children: <Widget>[
Image.asset('.../...'),
Text(products[index])
]
)
)
}
这种方法更加节省资源, 只会创建在页面上能看见的widget ,未出现的不会创建后占用内存
然后, 当我们想在另一个文件中使用listview, 我们需要添加Expanded
Expanded(
child: pattern()
)
Tabs & Drawers
添加tab bars, 用DefaultTabController 来wrap整个widget, 然后在body中最外层使用TabView
tabs
bottom
使用 bottonNavigationbars
bottomNavigationBar:
TabBar(
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Colors.grey,
tabs: <Widget>[
Tab(
icon: Icon(Icons.create),
text: 'create product',
),
Tab(
icon: Icon(Icons.list),
text: 'my products',
)
],
),
top
在appbar 添加一个bottom 属性, 然后再用TabBar
appBar: AppBar(
title: Text('title'),
bottom:
TabBar(
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Colors.grey,
tabs: <Widget>[
Tab(
icon: Icon(Icons.create),
text: 'create product',
),
Tab(
icon: Icon(Icons.list),
text: 'my products',
)
],
),
)
drawers
单独添加drawer组件
drawer: Drawer(
child: Column(
children: <Widget>[
AppBar(
automaticallyImplyLeading: false,
title: Text('choose'),
),
ListTile(
title: Text('Manage Products'),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
ProductCenter()));
},
),
ListTile(
title: Text('Home'),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) => Home()));
},
)
],
),
),
先在外层用Column,这样可以添加组件列表,
然后在组件列表里添加drawer里要显示的Appbar(automaticallyImplyLeading: false 默认为true的时候, 会在drawer的appbar中再添加一个) , 和 ListTiles(每个ListTile对应了一个按钮栏)
Container
padding
EdgeInsets
decoration
decoration: BoxDecoration(
color: //,
border: Border(
bottom: BorderSide()
Top://
Left://
Right://
)
)
Row / Column
mainAxisAlignment// x轴布局
crossAxisAlignment//y轴布局
Flutter navigation
向 stack 里pop and push 会销毁所有的数据,因此要保留数据的话 ,需要用到路由管理
push
onPressed: ()=>Navigator.push<returnType>(
context,// contains the infomation of current widget
MaterialPageRoute(
build: (BuildContext buildcontext) => SomeWidget(param1, param2)
)
).then(
(returnType value) {
print(value)
}
)
pushReplacement
同push , 但是替代当前stack,表现为无返回按钮
pushReplacementNamed
flutter中的路由管理, 用路径名代替builder,需要用到Navigator. pushReplacementNamed方法
在main中设置:
MaterialApp{
theme: ,
home: Auth(),
routes: //添加routes属性
{
'/admin': (BuildContext context) => ProductCenter(),
'/Home': (BuildContext context) => Home(this.products, this.deleteProduct, this.addProduct),
}, // 注意’/‘ 路径默认分配给home属性, 所以Auth 对应 ’/‘
}
一种特殊情况, 假设有一个ListView, 我们知道要用ListView.builder{ } 来传入一个itemBuilder widget 带一个index参数, 和一个itemCount。那么我们如果要制作一个详情页, 要求把每一个Item单独传入, 那么我们用builder的时候 会写成:
onPressed: ()=>Navigator.push<returnType>(
context,// contains the infomation of current widget
MaterialPageRoute(
build: (BuildContext buildcontext) => SomeWidget(List[index])
)
).then(
(returnType value) {
print(value)
}
)
但是怎么改成路由呢?
flutter不支持类似/home/{index} 类似的写法
instead,在main里, 可以在route后添加onGenerateRoute(RouteSettings settings)
Routesettings 包含了路径名
onGenerateRoute: (RouteSettings settings) {
final List<String> pathElement = settings.name.split('/');
if (pathElement[0] != '') {
return null;
}
if (pathElement[1] == 'product') {
final int index = int.parse(pathElement[2]);
return MaterialPageRoute<bool>(
builder: (BuildContext context) => ProductPage(
products[index]));
}
},
pop
对自定义按钮:
onpressed: () => Navigator.pop(context, true/false)
对实体按钮/默认返回按钮:
wrap the widget with WillPopScope
如果要用navigator另外pop带数据返回, 则默认Future.value为false
WillPopScope(
...
,
onWillPoped: () {
Navigator.pop(context, false)
return Future.value(false)
}
)
Dart 语法
const and final
- final 指代, 某一个variable 一旦在内存中创建之后, 不能再创建新的variable, 只能在原有基础上进行更改
- const 使变量创建好之后 , 无法对其内容进行进一步更改
[] and {} in constructor
{} | make param named params |
---|---|
[] | make param optional |
传参
使得不同页面之间传递参数非常方便
- regular data type
- function
- map
class MyApp extends StatelessWidget(
final String string;
final int int;
final Map<String ,dynamic> myMap;
final function onDelete;
MyApp(this.string, this.int, this.myApp, this.onDelete);
Widget build(BuildContext context){
return ...
}
)
私有函数
私有函数以划线开头