簡單列舉總結(jié)一下常用的布局widget钻注。
Flutter有豐富的layout組件庫。其中有一些是常用庫配猫。
下面的widget分為兩類:標準組件和來自Material Components的特殊組件幅恋。
只有Material App能夠使用Material Components的組件。
標準組件 - Standard widgets
- Container
- 給一個組件添加 padding, margins, 邊界(borders), 背景顏色或其它裝飾(decorations)泵肄。
- GridView
- 將多個widget放在一個可滑動的表格中捆交。
- ListView
- 將多個widget放在一個可滑動的列表中。
- Stack
- 在一個widget上面蓋上另一個widget腐巢。
Material Components
- Card
- 將一些相近的信息裝進一個有圓角和陰影的盒子里冯勉。
- ListTile
- 一個Row中裝載最多3行文字饿这;可選則在前面或尾部添加圖標衡载。
Container
Container
用法比較自由贞绵”睿可以把整個layout放進container里面绊袋,然后改變背景顏色或圖片努隙。
Container 小結(jié):
- 添加 padding, margins, 和邊界(borders)
- 能夠更好背景顏色和圖片
- 包含一個單獨的子widget腐碱,這個子widget可以是Row洁墙、Column或一個widget樹的根widget
測試代碼widgetdemo/container_page.dart
import 'package:flutter/material.dart';
import 'package:demo_flutter/widgetdemo/container_page.dart';
// 引入自定義的包......
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Container demo 1',
theme: new ThemeData(primarySwatch: Colors.brown),
home: new ContainerDemoPage(), // 這里換上想要測試的界面
);
}
}
widgetdemo/container_page.dart
代碼
import 'package:flutter/material.dart';
/// container示例界面
class ContainerDemoPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _ContainerDemoPageState();
}
class _ContainerDemoPageState extends State<ContainerDemoPage> {
@override
Widget build(BuildContext context) {
Expanded imageExpanded(String img) {
return new Expanded(child: new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 10.0, color: Colors.black38),
borderRadius: const BorderRadius.all(
const Radius.circular(8.0))),
margin: const EdgeInsets.all(4.0),
child: new Image.asset(img),
));
}
var container = new Container(
decoration: new BoxDecoration(color: Colors.black26),
child: new Column(
children: <Widget>[
new Row(children: <Widget>[
imageExpanded('images/c1.jpg'),
imageExpanded('images/c2.jpg'),
],),
new Row(children: <Widget>[
imageExpanded('images/d1.jpg'),
imageExpanded('images/d2.jpg'),
],),
new Row(children: <Widget>[
imageExpanded('images/p1.jpg'),
],)
],
),
);
return new Scaffold(
appBar: new AppBar(title: new Text('Container Page demo'),),
body: new Center(
child: container,
),
);
}
}
GridView
用GridView來將widget放入一個2維的列表中蛹疯。
GridView提供了2個預裝配好的列表,也可以自己建立自定義列表热监。
GridView支持滾動捺弦。
GridView 小結(jié):
- 將多個widget放進一個表格中
- 當超出渲染范圍時,自動提供滾動功能
- 可自定義格子孝扛,也可用下面提供的2種
- GridView.count 指定列的數(shù)目
- GridView.extent 允許指定子項的最大像素寬度
示例1 - 用GridView.extent
GridView.extent
指定子項占據(jù)的最大寬度
import 'package:flutter/material.dart';
/// gridView示例界面1
class GridDemo1Page extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _GridDemo1PageState();
}
class _GridDemo1PageState extends State<GridDemo1Page> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Grid Page 1 demo'),),
body: new Center(
child: buildGrid(),
),
);
}
List<Container> _buildGridTileList(int count) {
return new List<Container>.generate(count, (int index) =>
new Container(child: new Image.asset('images/pic${index + 1}.jpg'),));
}
Widget buildGrid() {
return new GridView.extent(
maxCrossAxisExtent: 150.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: _buildGridTileList(30),);
}
}
示例2 - 用GridView.count
crossAxisCount
設(shè)為2列吼,分成2列。
Widget buildGrid() {
var countGrid = GridView.count(
crossAxisCount: 2,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
padding: const EdgeInsets.all(4.0),
childAspectRatio: 1.3,
children: _buildGridTileList(30),
);
return countGrid;
}
ListView
ListView能以列的形式展示數(shù)據(jù)苦始。當內(nèi)容超過渲染范圍時寞钥,自動提供滾動的功能。
ListView 小結(jié)
- 把子視圖裝進列表中
- 水平或豎直都可以
- 支持滑動
- 相比于Column陌选,可選配置比較少理郑,但更易用并且支持滑動
和Android中的ListView差別不大
示例1
把ListTile
當做子項來裝載數(shù)據(jù)蹄溉。
import 'package:flutter/material.dart';
class ListViewPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _ListViewPageState();
}
class _ListViewPageState extends State<ListViewPage> {
@override
Widget build(BuildContext context) {
List<Widget> list = <Widget>[];
for (int i = 0; i < 30; i++) {
list.add(new ListTile(
title: new Text('title$i', style: _itemTextStyle,),
subtitle: new Text('A'),
leading: i % 3 == 0
? new Icon(Icons.theaters, color: Colors.blue,)
: new Icon(Icons.restaurant, color: Colors.blue,),
));
}
return new Scaffold(
appBar: new AppBar(title: new Text('ListView Demo'),),
body: new Center(child: new ListView(children: list,),),
);
}
}
TextStyle _itemTextStyle = new TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0);
另外可以參考 https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/colors_demo.dart
Stack
使用Stack在widget之上顯示另一些widget,通常用來顯示圖片您炉。
顯示的widget可以完全地把底部widget蓋住柒爵。
Stack 小結(jié):
- 用來在當前widget上面再蓋上一層widget
- Stack children中的第一個widget放在最下,后面的widget會一層層蓋上去
- Stack的內(nèi)容不支持滾動
- 可以裁剪超出范圍的子widget
Stack示例1
顯示一個CircleAvatar
import 'package:flutter/material.dart';
class StackPage1 extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _StackPage1State();
}
class _StackPage1State extends State<StackPage1> {
@override
Widget build(BuildContext context) {
var stack = new Stack(
alignment: const Alignment(0.6, 0.6),
children: <Widget>[
new CircleAvatar(
backgroundImage: new AssetImage('images/android_1.jpg'),
radius: 100.0,),
new Container(decoration: new BoxDecoration(color: Colors.black45),
child: new Text(
'Android Avatar', style: new TextStyle(color: Colors.white70),),),
new Container(decoration: new BoxDecoration(color: Colors.transparent),
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 100.0, 0.0),
child: new CircleAvatar(
backgroundImage: new AssetImage('images/p_box1.png'),
backgroundColor: Colors.transparent,
radius: 10.0,),),
],
);
return new Scaffold(
appBar: new AppBar(title: new Text('Stack Demo 1'),),
body: new Center(child: stack,),
);
}
}
Card
Card來自Material組件庫赚爵,可包含一些數(shù)據(jù)棉胀,通常用ListTile來組裝。Card只有一個子widget冀膝,可以是column唁奢、row、list窝剖、grid或其它組合widget驮瞧。
默認情況下,Card把自己的尺寸縮小為0像素枯芬÷郾剩可以用SizedBox來指定card的尺寸。
Flutter中的Card有圓角和陰影效果千所。修改elevation
可改變陰影效果狂魔。
elevation
取值范圍,參考 Elevation and Shadows
若設(shè)置的范圍外的值淫痰,陰影效果會消失最楷。
Card 小結(jié):
- 實現(xiàn)了Material Design card
- 用于展示相關(guān)的數(shù)據(jù)
- 有一個子項(child),可以是column待错、row籽孙、list、grid或其它組合widget
- 有圓角和陰影效果
- 不支持滾動
Card示例1
將前面的ListView示例修改一下
import 'package:flutter/material.dart';
class ListViewPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _ListViewPageState();
}
class _ListViewPageState extends State<ListViewPage> {
@override
Widget build(BuildContext context) {
List<Widget> list = <Widget>[];
for (int i = 0; i < 30; i++) {
list.add(new Card(child: new Column(
children: <Widget>[
new Image.asset(
'images/pic${i + 1}.jpg',),
new ListTile(
title: new Text('title$i', style: _itemTextStyle,),
subtitle: new Text('A'),
leading: i % 3 == 0
? new Icon(Icons.theaters, color: Colors.blue,)
: new Icon(Icons.restaurant, color: Colors.blue,),
),
],
),));
}
return new Scaffold(
appBar: new AppBar(title: new Text('ListView Demo'),),
body: new Center(child: new ListView(children: list,),),
);
}
}
TextStyle _itemTextStyle = new TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0);
ListTile
來自Material組件庫的橫向組件火俄》附ǎ可自定義3行文字及其可選的頭尾圖標。
此控件常與Card或ListView一起用瓜客。
ListTile 小結(jié):
- 可定制3行帶圖標的文字
- 相比于Row适瓦,配置更少,但更易用
加一個主界面
放置一些按鈕谱仪,點擊跳轉(zhuǎn)到相應(yīng)的界面玻熙。
使用Navigator.of(context).pushNamed(routeName)
來跳轉(zhuǎn)。
import 'package:flutter/material.dart';
import 'package:demo_flutter/widgetdemo/container_page.dart';
import 'package:demo_flutter/widgetdemo/grid_page.dart';
import 'package:demo_flutter/widgetdemo/listview_demo.dart';
import 'package:demo_flutter/widgetdemo/stack_page1.dart';
import 'package:demo_flutter/widgetdemo/button_page.dart';
const String CONTAINER_DEMO_PAGE = '/a';
void main() {
runApp(new MaterialApp(
home: new HomePage(),
routes: {
CONTAINER_DEMO_PAGE: (BuildContext context) => new ContainerDemoPage(),
'/b': (BuildContext context) => new GridDemo1Page(),
'/c': (BuildContext context) => new ListViewPage(),
'/d': (BuildContext context) => new StackPage1(),
'/e': (BuildContext context) => new ButtonPage(),
},
));
}
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
getGestureDetector(String routeName, String content) {
return new GestureDetector (
onTap: () {
Navigator.of(context).pushNamed(routeName);
},
child: new Container (
padding: EdgeInsets.all(20.0),
child: new Center(child: new Text (content),)),
);
}
return new Scaffold(
appBar: new AppBar(title: new Text('Home'),),
body: new Column(children: <Widget>[
getGestureDetector(CONTAINER_DEMO_PAGE, 'Container Demo'),
getGestureDetector('/b', 'Grid Demo 1'),
getGestureDetector('/c', 'ListView Demo'),
getGestureDetector('/d', 'Stack Demo'),
getGestureDetector('/e', 'Button Page'),
],),
);
}
}