組件目錄
- 基礎(chǔ)組件
- Text 文本
- Button 按鈕a
- Image 圖片
- TextField 輸入框振坚,TextFormField 表單
- Switch-開關(guān)羊娃,CheckBox-復(fù)選框熏挎,ProgressIndicator-進(jìn)度條
- 布局組件
- Column 和 Row 豎向或者橫向的線性布局
- Flex 彈性布局钩杰,按比例布局
- Wrap 流式布局
- Stack Positioned 絕對(duì)布局
- Align和Center 對(duì)齊與相對(duì)定位
- 容器組件
- Padding 留邊距
- Container 容器-內(nèi)外邊距隧哮,寬高
- 裝飾器Decoration 容器樣式修改 BoxDecoration幽勒,ShapeDecoration羽历,UnderlineTabIndicator等
- 約束Constraints 容器大小限制 ConstrainedBox焊虏,SizedBox,AspectRatio等
- 裁切類容器:ClipOval秕磷,ClipRRect诵闭,ClipRect
- Scaffold 頁面骨架
- 可滾動(dòng)組件
- ListView,GridView
- SingleScrollView
- CustomerScrollView
基礎(chǔ)組件
- Text 文本
- Button 按鈕
- Image 圖片
- TextField 輸入框澎嚣,TextFormField 表單
- Switch-開關(guān)疏尿,CheckBox-復(fù)選框,ProgressIndicator-進(jìn)度條
Text
Text(
"flutter text",
overflow: TextOverflow.clip,
textAlign: TextAlign.center, //textAlign 優(yōu)先
textDirection: TextDirection.rtl, //textAlign 優(yōu)先
style: TextStyle(),
),
Text.rich
Text.rich(
TextSpan(children: [
TextSpan(
text: "藍(lán)色字體的文本",
style: TextStyle(color: Colors.blue),
),
TextSpan(
text: "紅色字體的文本",
style: TextStyle(color: Colors.red),
),
TextSpan(
text: "大號(hào)的黃色字體文本",
style: TextStyle(color: Colors.yellow, fontSize: 30),
),
]),
style: TextStyle(fontSize: 4),
textAlign: TextAlign.left,
)
Button
- FlatButton--扁平的Button
- RaisedButton--凸起的易桃,有陰影褥琐,點(diǎn)擊有浮動(dòng)效果
- OutlineButton--有邊框的按鈕
-
IconButton--圖標(biāo)按鈕,不能加文字
widget_button
自定義Button
常用屬性有:
highlightColor: Colors.green,//按鈕按下的背景顏色
splashColor: Colors.blue,//水波紋顏色
color: Colors.red,//背景顏色
disabledColor: Colors.black12,////按鈕禁用的顏色
shape:ShapeBorder//形狀
ShapeBorder主要有以下子類:
- RoundedRectangleBorder 圓角形
- BeveledRectangleBorder 尖括號(hào)形狀
- CircleBorder 直接圓形
- ContinuousRectangleBorder 矩形
- StadiumBorder 操場(chǎng)400米跑道形狀
- UnderlineInputBorder 下劃線
Image
文件圖片晤郑,網(wǎng)絡(luò)圖片敌呈,資源圖片贸宏,內(nèi)存中的圖片
兩種寫法:
Image(
image: NetworkImage(image_0),
width: 100,
),
Image.network(image_0, width: 100, height: 100),
屬性:
this.width, //圖片的寬
this.height, //圖片高度
this.color, //圖片的混合色值
this.colorBlendMode, //混合模式
this.fit,//縮放模式
this.alignment = Alignment.center, //對(duì)齊方式
this.repeat = ImageRepeat.noRepeat, //重復(fù)方式
縮放模式 fit,直接看圖對(duì)比
<article id="content" class="article-content" tabindex="0" style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); outline-style: none;">
TextField 和 TextFormField 輸入框和表單提交校驗(yàn)
TextField(
//控制器磕洪,可以獲取文本內(nèi)容吭练,清空文本框等操作_textEditingController=TextEditingController()
controller: _textEditingController,
//文本樣式
style: TextStyle(
fontSize: 40,
color: Colors.red,
),
maxLines:10,//最大行數(shù)
minLines: 1,//最小行數(shù)--當(dāng)字?jǐn)?shù)超過一行的時(shí)候會(huì)自動(dòng)增加高度變成兩行
onChanged: (value) => {
//文字變化回調(diào)
setState(() {
textFieldStr = value;
})
},
),
TextField的屬性很多,常用的看注釋
TextFormField(
//當(dāng)點(diǎn)擊空白處的時(shí)候可以使用_focusNodePhone.unfocus()失去焦點(diǎn)進(jìn)行影藏鍵盤
focusNode: _focusNodePhone,
autofocus: true,
//控制器
controller: _phoneController,
//輸入框裝飾器
decoration: InputDecoration(
labelText: "手機(jī)號(hào)",
hintText: "請(qǐng)輸入手機(jī)號(hào)",
prefixIcon: Icon(
Icons.phone_android,
),
),
//表單提交褐鸥,規(guī)則校驗(yàn)
validator: (value) {
if (value.startsWith("1") && value.length == 11) {
return null;
} else {
return "手機(jī)號(hào)不對(duì)";
}
},
),
開關(guān):Switch
Switch(
value: isOpen,
onChanged: (value) {
setState(() {
isOpen = value;
});
},
復(fù)選框:Checkbox
Checkbox(
value: isOpen,
onChanged: (value) {
setState(() {
isOpen = value;
});
},
進(jìn)度條 ProgressIndicator
CircularProgressIndicator -- 圓形
LinearProgressIndicator -- 線性
RefreshProgressIndicator -- 類似于下拉刷新的圓形進(jìn)度條
布局類組件
- Column 和 Row 豎向或者橫向的線性布局
- Flex 彈性布局线脚,按比例布局
- Wrap 流式布局
- Stack Positioned 絕對(duì)布局
- Align和Center 對(duì)齊與相對(duì)定位
Column 和 Row 豎向或者橫向的線性布局
以Column為例講解,3個(gè)屬性比較重要:
- mainAxisAlignment 主軸方向的對(duì)齊方式
- crossAxisAlignment 縱軸方向的對(duì)齊方式
- children 孩子Widget
mainAxisAlignment有6個(gè)
- start
- end
- center
- spaceBetween
- spaceAround
- spaceEvenly
具體效果看下圖
Column(
mainAxisAlignment: MainAxisAlignment.start,//主軸方向的對(duì)齊方式
crossAxisAlignment: CrossAxisAlignment.start,//縱軸方向的對(duì)齊方式
children: <Widget>[
Text("start"),
Text("start"),
Text("start"),
Text("start"),
Text("start"),
],
),
crossAxisAlignment屬性常用的有3個(gè)
- start
- center
- end
Flex 彈性布局叫榕,按比例布局
- Column和Row是繼承Flex浑侥,用Flex也能實(shí)現(xiàn)兩者的效果
- 用Flex實(shí)現(xiàn)按比例布局,需要結(jié)合Expanded進(jìn)行指定比例
Flex(
direction: Axis.horizontal,//如果是垂直的話晰绎,需要指定父容器的高度寓落,否則會(huì)報(bào)錯(cuò)
children: <Widget>[
Expanded(
flex: 1,//占
child: Container(color: Colors.orange, child: Text("flex=1")),
),
Expanded(
flex: 2,
child: Container(color: Colors.red, child: Text("flex=2")),
),
],
),
Wrap 流式布局
使用方式和Row和Colunm類似,會(huì)自動(dòng)換行
Container(
color: Colors.blue,
height: 400,
child: Wrap(
//水平方向
direction: Axis.horizontal,
//主軸上child的間距
spacing: 10,
//縱軸child的間距
runSpacing: 50,
//主軸child的對(duì)齊方式
alignment: WrapAlignment.start,
//縱軸child的對(duì)齊方式
runAlignment: WrapAlignment.spaceEvenly,
//縱軸居中對(duì)齊
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
Container(color: Colors.red, child: Text("AAAAAAAAAAAAAA")),
Container(
color: Colors.red,
child: OutlineButton(
child: Text("CCCCCCCCCCCCCCC"),
onPressed: () => {},
),
),
Container(color: Colors.red, child: Text("SSSSSSSSS")),
Container(color: Colors.red, child: Text("AAAAAA")),
Container(
color: Colors.red,
child: OutlineButton(
child: Text("按鈕1111"),
onPressed: () => {},
),
),
],
),
),
Stack Positioned 絕對(duì)布局
Stack:絕對(duì)布局荞下,使用Positioned進(jìn)行定位伶选,子widget相對(duì)于父widget進(jìn)行定位
Container(
height: 100,
color: Colors.red,
child: ConstrainedBox(
constraints: BoxConstraints.expand(), //撐滿父容器
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(left: 0, top: 0, child: Text("左上角")),
Positioned(right: 0, top: 0, child: Text("右上角")),
Positioned(left: 0, bottom: 0, child: Text("左下角")),
Positioned(right: 0, bottom: 0, child: Text("右下角")),
//這里水平使用外層設(shè)置的居中對(duì)齊方式
Positioned(top: 0, child: Text("AA")),
//這里垂直和水平都是外層設(shè)置的居中對(duì)齊方式
Positioned(child: Text("BB")),
Positioned(bottom: 0, child: Text("CC")),
],
),
),
),
Align和Center,對(duì)齊與相對(duì)定位
單一孩子Widget尖昏,設(shè)置子組件的位置仰税,并且根據(jù)子組件的大小設(shè)置自己的大小,Center是Align的一個(gè)包裝類抽诉,不能設(shè)置對(duì)齊方式陨簇,對(duì)齊方式是居中對(duì)齊
Column(
children: <Widget>[
Container(
color: Colors.red,
child: Align(
//子Widget
child: Container(
color: Colors.blue,
child: Text("AAAAA"),
),
/*父Widget的寬度是子Widget的3倍*/
widthFactor: 3,
/*父Widget的高度是子Widget的2倍*/
heightFactor: 2,
alignment: Alignment.center,//或者 FractionalOffset(0.5, 0.5),
),
),
Container(
margin: EdgeInsets.only(top: 20),
color: Colors.red,
child: Center(
//子Widget
child: Container(
color: Colors.blue,
child: Text("AAAAA"),
),
/*父Widget的寬度是子Widget的3倍*/
widthFactor: 3,
/*父Widget的高度是子Widget的2倍*/
heightFactor: 2,
),
),
],
),
容器類組件
- Padding 留邊距
- Container 容器-內(nèi)外邊距,寬高
- 裝飾器Decoration 容器樣式修改 BoxDecoration迹淌,ShapeDecoration河绽,UnderlineTabIndicator等
- 約束Constraints 容器大小限制 ConstrainedBox,SizedBox唉窃,AspectRatio等
- 裁切類容器:ClipOval耙饰,ClipRRect,ClipRect
- Scaffold 頁面骨架
Padding 內(nèi)邊距
Padding(
child: Text("AAAAAAAA"),
padding: EdgeInsets.fromLTRB(10,100, 30, 80),//依次為左纹份,上苟跪,右,下設(shè)置邊距
),
還可以使用以下方式快速添加邊距蔓涧,適應(yīng)不同場(chǎng)景的需求
padding: EdgeInsets.all(10),//4個(gè)邊都留10邊距
padding: EdgeInsets.only(left: 10,bottom: 20),//可選參數(shù)件已,指定哪條邊留邊距
padding: EdgeInsets.symmetric(vertical: 10,horizontal: 20),//可選參數(shù),上下邊距10蠢笋,左右邊距20
Container 容器-內(nèi)外邊距拨齐,寬高
Container(
width: 300,//容器寬
height: 200,//容器高
padding: EdgeInsets.all(20),//內(nèi)邊距
margin: EdgeInsets.all(20),//外邊距
// color: Colors.red,//背景色,和decoration屬性互斥昨寞,只能設(shè)置一個(gè)瞻惋,否則會(huì)報(bào)錯(cuò)
//裝飾器
// decoration: ShapeDecoration(color: Colors.red, shape: CircleBorder()),
decoration: BoxDecoration(
color: Colors.blue,//背景顏色
borderRadius: BorderRadius.circular(20), //圓角
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black26, //陰影的顏色
blurRadius: 10, //虛化的寬度
spreadRadius: 10, //陰影和原物大小的差值--不包括虛化的部分
offset: Offset(40, 40), //陰影的偏移量
),
],
),
//容器約束-大小限制
constraints: BoxConstraints(
minHeight: 100,
minWidth: 100,
maxWidth: 200,//這里限制了200厦滤,所以上面設(shè)置的寬度300無效
maxHeight: 150,
),
child: Text("AAAAAAAA"),
),
裝飾器Decoration
上面Conatiner中用到了一個(gè)BoxDecoration,用于裝飾Container容器的樣式歼狼,圓角掏导,背景色,陰影等羽峰,其實(shí)Container內(nèi)部使用的是DecoratedBox趟咆,只是進(jìn)行了一次封裝,方便使用梅屉。Flutter除了提供BoxDecoration值纱,還有ShapeDecoration,UnderlineTabIndicator坯汤,F(xiàn)lutterLogoDecoration虐唠,他們都是Decoration的子類。
約束Constraints
約束容器的大小惰聂,上面代碼中的Container限制了最大最小的寬高疆偿,內(nèi)部實(shí)現(xiàn)也是進(jìn)行了一次封裝,使用的是ConstrainedBox搓幌,另外Flutter還提供了SliverConstraints杆故,在滾動(dòng)布局中進(jìn)行約束
如果不使用Container,直接使用DecoratedBox和ConstrainedBox也是可以的溉愁,自己去實(shí)現(xiàn)child处铛,如下使用:
DecoratedBox(
decoration: BoxDecoration(
//背景顏色
color: Colors.blue, //圓角
borderRadius: BorderRadius.circular(20),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.black26, //陰影的顏色
blurRadius: 10, //虛化的寬度
spreadRadius: 10, //陰影和原物大小的差值--不包括虛化的部分
offset: Offset(40, 40), //陰影的偏移量
),
],
),
child: Text("AAAAAAAA"),
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: 100,
minWidth: 100,
maxWidth: 200, //這里限制了200,所以上面設(shè)置的寬度300無效
maxHeight: 150,
),
child: Container(
color: Colors.red,
width: 100,
child: Center(child: Text("AAAAAAA")),
),
),
尺寸限制容器:ConstrainedBox叉钥,SizedBox罢缸,AspectRatio等
ConstrainedBox:大小約束
SizedBox:指定大小的容器
UnconstrainedBox:解除父容器大小限制
AspectRatio:指定比例
他們都是SingleChildRenderObjectWidget的子類篙贸,都只有一個(gè)child widget投队。
Container(
margin: EdgeInsets.only(top: 10),
child: SizedBox(
width: 100,
height: 100,
child: Container(
color: Colors.red,
width: 50,//這里設(shè)置無效
height: 200,//這里設(shè)置無效
child: Center(child: Text("AAAAAAA")),
),
),
),
Container(
margin: EdgeInsets.only(top: 20),
width: 100, //指定寬為100
child: AspectRatio(
aspectRatio: 0.5, //父容器寬為100,寬高比為0.5爵川,則高度為200
child: Container(
color: Colors.red,
child: Text(
"11111111111111111111111111111111111111111111111111111111111111111111111111111"
"11111111111111111111111111111111111111111111111111111111111111111111111111"
"11111111111111111111111111111111111111111111111111111111111111111111111111"),
),
),
),
裁切類容器:ClipOval敷鸦,ClipRRect,ClipRect
圓形頭像寝贡,圓角矩形扒披,矩形裁切
ClipOval(
child: Image.network(
IMAGE_0,
fit: BoxFit.cover,
width: 50,
height: 50,
),
),
ClipRect(
child: Container(
color: Colors.black12,
child: Image.network(
IMAGE_0,
fit: BoxFit.cover,
width: 100,
height: 100,
),
),
),
Container(
margin: EdgeInsets.only(top: 10),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(30),
),
child: Container(
color: Colors.black12,
child: Image.network(
IMAGE_0,
fit: BoxFit.cover,
width: 200,
height: 200,
),
),
),
)
Scaffold 骨架容器
- 完整的骨架容器包含了
- 頂部導(dǎo)航欄:appBar
- 內(nèi)容體:body
- 左側(cè)和右側(cè)的抽屜:drawer、endDrawer
- 底部菜單導(dǎo)航:bottomNavigationBar
- 懸浮按鈕:floatingActionButton
Scaffold(
//頂部導(dǎo)航
appBar: AppBar(
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: const Icon(Icons.menu),
onPressed: () => {
//點(diǎn)擊左上角的按鈕
Scaffold.of(context).openDrawer()
},
);
},
),
title: Text("Scaffold的使用"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.folder_shared),
onPressed: () => {},
),
IconButton(
icon: Icon(Icons.share),
onPressed: () => {},
),
],
bottom: TabBar(
controller: _tabController,
tabs: tabs.map((e) => Tab(text: e)).toList(),
),
),
//內(nèi)容體
body: TabBarView(
controller: _tabController,
children: <Widget>[
Center(child: Text(tabs[0])),
Center(child: Text(tabs[1])),
Center(child: Text(tabs[2])),
],
),
//左邊抽屜
drawer: Container(
width: 250,
color: Colors.white,
child: Center(
child: FlatButton(
child: Text("左側(cè)抽屜"),
onPressed: () => {},
),
),
),
//右邊抽屜
endDrawer: Drawer(
child: MediaQuery.removePadding(
context: context, // removeTop: true,//移除抽屜菜單頂部默認(rèn)留白
child: ListView(
children: <Widget>[
ListTile(leading: const Icon(Icons.add), title: const Text('Add account0')),
ListTile(leading: const Icon(Icons.add), title: const Text('Add account1')),
ListTile(leading: const Icon(Icons.add), title: const Text('Add account2')),
ListTile(leading: const Icon(Icons.add), title: const Text('Add account3')),
],
),
),
),
//底部菜單導(dǎo)航
bottomNavigationBar: BottomNavigationBar(
currentIndex: index,
onTap: (i) => {
setState(() {
index = i;
})
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.map), title: Text(tabs[0])),
BottomNavigationBarItem(icon: Icon(Icons.map), title: Text(tabs[1])),
BottomNavigationBarItem(icon: Icon(Icons.map), title: Text(tabs[2])),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => {},
),
);
<article id="content" class="article-content" tabindex="0" style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); outline-style: none;">
滾動(dòng)組件
- ListView圃泡,GridView
- SingleScrollView
- CustomerScrollView
滾動(dòng)組件分為兩類:
- 具有延遲加載特性的滾動(dòng)組件碟案,如:ListView,GridView
- 一次性加載所有組件,如SingleChildScrollView
如果說頁面上的內(nèi)容很多颇蜡,大大的超過了一個(gè)屏幕价说,使用SingleChildScrollView辆亏,會(huì)比較耗內(nèi)存,性能也會(huì)比較差
建議使用ListView或者GridView這種具有延遲加載特性的組件
下面使用ListView示例鳖目,屬性說明見代碼注釋
Container(
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
color: Colors.white,
child: ListView.builder(
itemExtent: 100, //指定子組件的高度扮叨,如果指定了效率更高,不用每次都去計(jì)算子組件的高度了
itemCount: 100, //子組件的個(gè)數(shù)
shrinkWrap: false, //ListView的高度是否是內(nèi)容包裹领迈,否則撐到最大,如果ListView的父容器沒有邊界彻磁,則必須設(shè)置為true
itemBuilder: (BuildContext context, int index) {
return Container(
height: 200, //上面指定了itemExtent之后,該屬性無效
margin: EdgeInsets.all(10), color: Colors.red,
);
},
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.yellow,
//帶分割線的ListView構(gòu)造函數(shù)
child: ListView.separated(
itemCount: 10, //子組件的個(gè)數(shù)
shrinkWrap: false, //ListView的高度是否是內(nèi)容包裹狸捅,否則撐到最大,如果ListView的父容器沒有邊界衷蜓,則必須設(shè)置為true
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100, //上面指定了itemExtent之后,該屬性無效
// margin: EdgeInsets.fromLTRB(10, 5, 10, 5),
color: Colors.blue,
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: Colors.black,
height: 30,
//間距的高度-包括了線的高度
thickness: 0.1,
//線條的高度
indent: 10,
//左邊距
endIndent: 10, //右邊距
);
},
),
),
),
],
)),
使用SingleScrollView
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 100,
color: Colors.red,
child: Center(
child: Text("SingleChildScrollView的使用"),
),
),
Container(
height: 400,
color: Colors.blue,
child: Center(
child: Text("SingleChildScrollView的使用"),
),
),
Container(
height: 400,
color: Colors.yellow,
child: Center(
child: Text("SingleChildScrollView的使用"),
),
),
],
),