一、Container
是一個便利的Widget,它把通用的繪制、定位和Widget的大小結合了起來。
Container會先用padding填充子Widget和border之間的空白,然后添加其他的額外的約束constraints,最后會把剩余的都用margin來填充。
在繪制的過程中,會優先繪制transform,然后是decoration,最后是foregroundDecoration。
對于一個沒有子Widget的Container,在沒有一些約束的條件時,它會盡可能的大;而一旦有了約束或者子Widget,它就會變得盡可能小。
下面是代碼演示時間:
- 沒有任何子Widget時
static _baseContainer() {
return new Container(
color: Colors.red,
);
}
此時的截圖如下:發現它盡可能的占了全部。
此時,設置padding是不起作用的。
- 沒有其他約束,只有一個子widget時
static _addWidgetToContainer() {
return new Container(
color: Colors.red,
child: new Text("Container"),
);
}
此時變成了下面的樣子:它幾乎和子Widget貼合到了一起了。
- 當限制了寬度的時候
static _limitWidth() {
return new Container(
color: Colors.red,
child: new Text("Container"),
width: 20.0,
// width: 200.0,
// height: 10.0,
);
}
可以肯定,文字的寬度要比20大,因為此時沒有限制高度,所以會展示成下面的樣子:可以發現它的高度自動變大了,直到能把所有的內容容納下來。
-
當限制了高度的時候
假設這個時候寬度是足夠的,如果限制了高度,高度如果足夠,則會正常展示,但是如果高度不夠的時候就會出現越界的現象,如下所示:
image.png
如果我指定了寬度和高度里的一個,而沒有一些約束和子Widget,未指定的會盡可能最大。
-
當限制了寬和高的時候
可以確定,寬高足夠的時候,是能夠完美展示的。如果寬度不夠,高度也不夠呢,會是什么樣的展示呢?
image.png - 限定寬度或者高度,指定padding
當padding的寬度超過了width,則會默認保留左padding或者上padding。
static _limitWidthWithPadding() {
return new Container(
color: Colors.red,
padding: const EdgeInsets.all(20.0),
height: 20.0,
width: 20.0,
child: new Text("Container"),
);
}
- contraints約束
static _boxContraints() {
return new Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
// 相當于直接制定了該Container的寬和高,且它的優先級要高于width和height
constraints: new BoxConstraints.expand(width: 250.0, height: 150.0),
color: Colors.red,
width: 100.0,
height: 100.0,
// 設置Container的最大和最小寬度和高度
// constraints: new BoxConstraints(
// maxWidth: 50.0,
// ),
),
new Container(
color: Colors.green,
width: 100.0,
height: 100.0,
)
],
);
}
這里主要展示了它的默認初始化和指定初始化方法的Expand,其中后者就相當于直接制定了該Container的寬和高。
-
foregroundDecoration
這個比較重要,它會堵在Container的所有子Widget的前面,另外還有一些圓角和背景的問題,具體的見下圖:
image.png
代碼為:
static _foregroundDecoration() {
return new Center(
child: new Container(
color: Colors.red,
constraints: new BoxConstraints.expand(width: 300.0, height: 300.0,),
foregroundDecoration: new BoxDecoration(
color: Colors.blue,
border: new Border.all(color: Colors.yellow, width: 5.0,),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
gradient: new LinearGradient(colors: [Colors.blue, Colors.green]),
),
alignment: Alignment.center,
child: new Text("Container"),
),
);
}
可以發現,對于有背景圖的Container,只是簡單的切圓角是有問題的;而且它還會堵住子Widget。
-
decoration
針對上面提到的會堵住子Widget和切角問題,decoration可以很好的解決問題,不過這里需要注意??:Container的color和該屬性不能共存。所以最后的代碼和效果圖如下:
image.png
static _decoration() {
return new Center(
child: new Container(
// color: Colors.red, // 不能和decoration共存
constraints: new BoxConstraints.expand(width: 300.0, height: 300.0,),
alignment: Alignment.center,
child: new Text("Container"),
decoration: new BoxDecoration(
color: Colors.blue,
border: new Border.all(color: Colors.yellow, width: 5.0,),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
gradient: new LinearGradient(colors: [Colors.blue, Colors.green]),
),
),
);
}
二、Row
Row在前面聊過,最主要注意的一點就是內容不能超過邊界,否則會出錯誤。
這里補充的是如果使用了Expanded,那么其中的Widget的尺寸就不再起作用。如下:
static _baseRow() {
return new Container(
color: Colors.red,
height: 300.0,
child: new Row(
// 會超出去,展示錯誤
// children: <Widget>[
// new Container(width: 200.0, color: Colors.green,),
// new Container(width: 200.0, color: Colors.blue,),
// new Container(width: 200.0, color: Colors.cyan,),
// ],
children: <Widget>[
// 使用了Expanded后,尺寸不再起作用
new Expanded(child: new Container(width: 50.0, color: Colors.green,)),
new Expanded(child: new Container(width: 100.0, color: Colors.blue,)),
new Expanded(child: new Container(width: 100.0, color: Colors.cyan,)),
],
),
);
}
這里的使用了Expanded的Container就不會再起作用
三、Column(同Row)
四、Text
有兩種初始化方法,Text和Text.rich。
五、Icon
Icon是不響應事件的,IconButton可以。
六、RaisedButton
通俗的翻譯:浮起來的按鈕,先看兩個截圖吧,有個直觀的認識:默認情況下,可以看到被點擊中的按鈕浮起來了。
注意??:它有個參數onPressed,如果沒有定義回調函數,則無論你怎么設置,該按鈕的狀態都是失效狀態,而且其他所有的屬性,只要是和disable無關的,無論怎么設置都不會起作用。
1、直接初始化
具體的詳細說明如下:
raisedButtonWithChild() {
return new Center(
child: new RaisedButton(
onPressed: this.clickedRaisedButton,
color: Colors.green,
// child: new Text('Raised Button', style: new TextStyle(color: Colors.black),),
child: new Text(
'Raised Button',
),
textColor: Colors.white, // 該按鈕上的文字顏色,但是前提是不設置字體自身的顏色時才會起作用
// highlightColor: Colors.yellow, // 高亮時的背景色
disabledColor: Colors.deepOrange, // 失效時的背景色
disabledTextColor: Colors.grey, // 按鈕失效時的文字顏色,同樣的不能使用文本自己的樣式或者顏色時才會 起作用
splashColor: Colors.purple, // 點擊按鈕時的漸變背景色,當你不設置高亮背景時才會看的更清楚
colorBrightness: Brightness.dark, // 這個我也不知道
elevation: 15.0, // 正常情況下浮動的距離
highlightElevation: 5.0, // 高亮時的浮動距離(可以嘗試將該值設置的比elevation小,看看體驗)
disabledElevation: 50.0,
padding: const EdgeInsets.all(20.0),
shape: new Border.all(
// 設置邊框樣式
color: Colors.blue,
width: 4.0,
style: BorderStyle.solid,
),
animationDuration: new Duration(
// 過程時間,最容易觀察的是從elevation到highlightElevation,或者相反過程,但是前提是要徹底的按下去,注意其影子的變化
seconds: 5,
),
onHighlightChanged: this.hightLightChanged, // 可以用來監聽按鈕的按下和放開過程
textTheme: ButtonTextTheme.accent, // 搞不懂這個
),
);
}
2、重定向icon初始化
該方法得到的RaisedButton默認有兩個Widget,而且是必傳的;其他參數都和直接初始化沒什么區別。具體的代碼如下:
raisedButtonWithIcon() {
return new Center(
child: new RaisedButton.icon(
onPressed: this.clickedRaisedButton,
icon: new Icon(Icons.star),
label: new Text('RaisedButton'),
),
);
}
效果圖如下:七、AppBar
這里有個官方的解釋圖,比較形象的說明了AppBar的結構:這里因為對其他的Widget還不熟悉,所以暫時沒辦法做bottom。做了一個效果圖,如下所示:
實現這部分的代碼如下:
class AppBarWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => new AppBarState();
}
class AppBarState extends State<AppBarWidget> {
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
debugShowCheckedModeBanner: false, // 在調試期間,右上角的DEBUG字樣
home: new Scaffold(
appBar: new AppBar(
title: new Text(
'AppBar',
style: new TextStyle(
// 設置字體樣式
color: Colors.white,
fontWeight: FontWeight.bold,
),
), // title
// centerTitle: true, // 當設置了actions之后,title的位置會發生變化,使用該屬性,可以讓標題忽略actions占去的空間居中
// titleSpacing: 0.0,
elevation: 0.0, // 下部的影子,該值越大,影子越清楚,為0時,不會有影子,和RaisedButton是一樣的
backgroundColor: Colors.cyan, // 背景色
leading: this.appBarLeading(),
actions: this.appBarActions(),
bottom: null, // 這個先放一放
// flexibleSpace: new FlexibleSpaceBar( // 這個有什么用呢????貌似是說只有在appbar的size改變的時候才會起作用
// title: new Text('Flexible'),
// // centerTitle: false,
// ),
),
),
);
}
appBarActions() {
return <Widget>[
new Container(
width: 50.0,
child: new Icon(
Icons.star_border,
color: Colors.red,
),
),
new Container(
width: 50.0,
child: new Icon(Icons.share),
),
new Container(
color: Colors.orange,
width: 50.0,
margin: const EdgeInsets.only(
left: 5.0,
right: 5.0,
),
alignment: Alignment.center,
child: new Text('actions'),
),
];
}
// 經過實驗發現,leading是限制了大小的
appBarLeading() {
return new RaisedButton(
onPressed: this.clickedLeadingBtn,
child: new Text(
'Leading',
),
textColor: Colors.white,
color: Colors.red,
elevation: 0.0,
disabledElevation: 0.0,
highlightElevation: 0.0,
// highlightColor: Colors.cyan,
colorBrightness: Brightness.light,
splashColor: Colors.red,
padding: const EdgeInsets.all(5.0),
);
}
clickedLeadingBtn() {
print('Clicked Leading');
}
}
八、FlutterLogo
用來展示Flutter的logo的,真是任性啊,為了一個Logo,專門寫了一個Widget。
class _FlutterLogoState extends State<_FlutterLogoWidget> {
var _status = 0;
clickedToChangeStatus() {
setState(() {
_status = (_status + 1) % 3;
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
FlutterLogoStyle style = FlutterLogoStyle.markOnly;
if (_status == 1) {
style = FlutterLogoStyle.horizontal;
} else if (_status == 2) {
style = FlutterLogoStyle.stacked;
}
return new Center(
child: new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(
top: 30.0,
bottom: 30.0,
),
child: new RaisedButton(
onPressed: this.clickedToChangeStatus,
color: Colors.green,
child: new Text('Change Status'),
),
),
new FlutterLogo(
size: 50.0,
colors: Colors.red, // 圖的顏色
textColor: Colors.orange, // 只對帶文字的style起作用
// style: FlutterLogoStyle.markOnly, // 只有圖
style: style, // 左圖右文
// style: FlutterLogoStyle.stacked, // 上圖下文
duration: new Duration(
// 當colors、textColor或者style變化的時候起作用
seconds: 3,
),
curve: Curves.elasticOut, // 動畫方式
)
],
),
);
}
}
九、PlaceHolder
通俗講,就是一個用來占位的Widget,提示開發人員,這里需要暫時保留。效果如下:代碼也很簡單,甚至不用多寫任何東西,只要初始化了就行了。
new Container(
width: 100.0,
margin: const EdgeInsets.only(top: 30.0),
child: new Placeholder(
fallbackWidth: 100.0,
fallbackHeight: 100.0,
color: Colors.orange,
),
)