博客地址:flutterall.com
本文我們就一起聊一聊Flutter中的Button析孽。由于Flutter是跨平臺的翰灾,所以有適用于Android和iOS的兩種風(fēng)格的組件枷畏。一套是Google極力推崇的Material,一套是iOS的Cupertino風(fēng)格的組件。無論哪種風(fēng)格,都是通用的。
Material與Cupertino風(fēng)格比較
控件 | Material | Cupertino |
---|---|---|
Button | RaisedButton
|
CupertinoButton
|
DatePick | showDatePicker
|
CupertinoDatePicker
|
從多年與設(shè)計師打交道來看亚享,App更青睞于iOS,很多Android的App做的跟iOS一樣一樣的盆犁,就連設(shè)計個按鈕圖標啥的都是一樣肚邢。
Material Style
RaisedButton(Material風(fēng)格的按鈕)
RaisedButton({
Key key,
//點擊按鈕的回調(diào)出發(fā)事件
@required VoidCallback onPressed,
//水波紋高亮變化回調(diào)
ValueChanged<bool> onHighlightChanged,
//按鈕的樣式(文字顏色、按鈕的最小大小摊溶,內(nèi)邊距以及shape)[ Used with [ButtonTheme] and [ButtonThemeData] to define a button's base
//colors, and the defaults for the button's minimum size, internal padding,and shape.]
ButtonTextTheme textTheme,
//文字顏色
Color textColor,
//按鈕被禁用時的文字顏色
Color disabledTextColor,
//按鈕的顏色
Color color,
//按鈕被禁用時的顏色
Color disabledColor,
//按鈕的水波紋亮起的顏色
Color highlightColor,
//水波紋的顏色
Color splashColor,
//按鈕主題高亮
Brightness colorBrightness,
//按鈕下面的陰影長度
double elevation,
//按鈕高亮?xí)r的下面的陰影長度
double highlightElevation,
double disabledElevation,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Clip clipBehavior = Clip.none,
MaterialTapTargetSize materialTapTargetSize,
Duration animationDuration,
Widget child,
}
一張圖了解RaisedButton
Code
RaisedButton(
textTheme: ButtonTextTheme.accent,
color: Colors.teal,
highlightColor: Colors.deepPurpleAccent,
splashColor: Colors.deepOrangeAccent,
colorBrightness: Brightness.dark,
elevation: 50.0,
highlightElevation: 100.0,
disabledElevation: 20.0,
onPressed: () {
//TODO
},
child: Text(
'RaisedButton',
style: TextStyle(color: Colors.white, fontSize: 40),
),
)
FloatingActionButton(懸浮按鈕)
如果有時間爬骤,可以看看FlatButton的Material設(shè)計理念,效果還是很不錯的莫换。
例如:
FloatingActionButton({
Key key,
// 按鈕上的組件霞玄,可以是Text、icon, etc.
this.child,
//長按提示
this.tooltip,
// child的顏色(盡在child沒有設(shè)置顏色時生效)
this.foregroundColor,
//背景色拉岁,也就是懸浮按鍵的顏色
this.backgroundColor,
this.heroTag = const _DefaultHeroTag(),
//陰影長度
this.elevation = 6.0,
//高亮?xí)r陰影長度
this.highlightElevation = 12.0,
//按下事件回調(diào)
@required this.onPressed,
//是小圖標還是大圖標
this.mini = false,
//按鈕的形狀(例如:矩形Border坷剧,圓形圖標CircleBorder)
this.shape = const CircleBorder(),
this.clipBehavior = Clip.none,
this.materialTapTargetSize,
this.isExtended = false,
})
Code
FloatingActionButton(
child: Icon(Icons.access_alarm),
tooltip: "ToolTip",
foregroundColor: Colors.white,
backgroundColor: Colors.deepPurple,
shape: const Border(),
onPressed: () {
//click callback
},
)
FlatButton
一個扁平的Material按鈕
FlatButton({
Key key,
@required VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme,
Color textColor,
Color disabledTextColor,
Color color,
Color disabledColor,
Color highlightColor,
Color splashColor,
Brightness colorBrightness,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Clip clipBehavior = Clip.none,
MaterialTapTargetSize materialTapTargetSize,
@required Widget child,
})
可以看到屬性跟RaisedButton類似,這里不多說了喊暖。
FlatButton(
onPressed: () {},
child: Text(
"FlatBtn",
style: TextStyle(fontSize: 20, color: Colors.deepPurple),
));
IconButton
圖標按鈕惫企,按下時會產(chǎn)生水波紋效果。
IconButton({
//這幾個屬性跟前面講的幾個差不多陵叽,這里就不再講了狞尔。如有疑問,請留言巩掺。
Key key,
this.iconSize = 24.0,
this.padding = const EdgeInsets.all(8.0),
this.alignment = Alignment.center,
@required this.icon,
this.color,
this.highlightColor,
this.splashColor,
this.disabledColor,
@required this.onPressed,
this.tooltip
})
DropdownButton
Material Style 下拉菜單按鈕
DropdownButton({
Key key,
//要顯示的列表
List<DropdownMenuItem<T>> @required this.items,
//下拉菜單選中的值(注意:在初始化時偏序,要么為null,這時顯示默認hint的值胖替;
// 如果自己設(shè)定值研儒,則值必須為列表中的一個值,如果不在列表中刊殉,會拋出異常)
T value,
//默認顯示的值
Widget hint,
Widget disabledHint,
//選中時的回調(diào)
ValueChanged<T> @required this.onChanged,
this.elevation = 8,
this.style,
this.iconSize = 24.0,
this.isDense = false,
this.isExpanded = false,
})
- items
//返回城市列表殉摔,寫法一
List<DropdownMenuItem> _getItems() {
List<DropdownMenuItem> items = new List();
//value 表示DropdownButton.onChanged的返回值
items.add(DropdownMenuItem(child: Text("北京"), value: "BJ"));
items.add(DropdownMenuItem(child: Text("上海"), value: "SH"));
items.add(DropdownMenuItem(child: Text("廣州"), value: "GZ"));
items.add(DropdownMenuItem(child: Text("深圳"), value: "SZ"));
return items;
}
//返回城市列表,寫法二
List<DropdownMenuItem<String>> _getCityList() {
var list = ["北京", "上海", "廣州", "深圳"];
return list.map((item) => DropdownMenuItem(
value: item,
child: Text(item),
)).toList();
}
由于我們在點擊每一個條目后记焊,展示的選中條目會變化逸月,所以DropdownButton應(yīng)當繼承StatefulWidget,在選中條目后也就是onChange的回調(diào)中使用setState((){})更新對象的狀態(tài)遍膜。
- DropdownButton
DropdownButton應(yīng)當繼承StatefulWidget
class FlutterDropdownButtonStatefulWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _DropdownState();
}
}
- _DropdownState
//下劃線開頭表示私有
class _DropdownState extends State<FlutterDropdownButtonStatefulWidget> {
// 下拉菜單選中的值(注意:在初始化時碗硬,要么為null瓤湘,這時顯示默認hint的值;
// 如果自己設(shè)定值恩尾,則值必須為列表中的一個值弛说,如果不在列表中,會拋出異常)
String selectValue;
@override
Widget build(BuildContext context) {
return DropdownButton(
//要顯示的條目
items: _getItems(),
//默認顯示的值
hint: Text("請選擇城市"),
//下拉菜單選中的值(注意:在初始化時翰意,要么為null木人,這時顯示默認hint的值;
// 如果自己設(shè)定值冀偶,則值必須為列表中的一個值醒第,如果不在列表中,會拋出異常)
value: selectValue,
onChanged: (itemValue) {//itemValue為選中的值
print("itemValue=$itemValue");
_onChanged(itemValue);
},
);
}
_onChanged(String value) {
//更新對象的狀態(tài)
setState(() {
selectValue = value;
});
}
}
-
print log
print log
-
最終效果
DropdownButton
PopupMenuButton
當菜單隱藏時进鸠,點擊并且調(diào)用onSelected時顯示一個彈出式菜單列表
PopupMenuButton({
Key key,
//構(gòu)建彈出式列表數(shù)據(jù)
PopupMenuItemBuilder<T> @required this.itemBuilder,
//初始值
T initialValue,
//選中時的回調(diào)
PopupMenuItemSelected<T> onSelected;,
//當未選中任何條目后彈窗消失時的回調(diào)
final PopupMenuCanceled onCanceled;,
//
this.tooltip,
//彈窗陰影高度
this.elevation = 8.0,
//邊距
this.padding = const EdgeInsets.all(8.0),
//彈窗的位置顯示的組件稠曼,默認為三個點...
this.child,
//跟child效果一致
this.icon,
//彈窗偏移位置
this.offset = Offset.zero,
})
- Code
import 'package:flutter/material.dart';
class FlutterPopupMenuButton extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PopupMenuState();
}
const List<String> models = const <String>['白天模式', '護眼模式', '黑夜模式'];
class _PopupMenuState extends State<FlutterPopupMenuButton> {
String title = models[0];
List<PopupMenuEntry<String>> _getItemBuilder() {
return models
.map((item) => PopupMenuItem<String>(
child: Text(item),
value: item,//value一定不能少
))
.toList();
}
void _select(String value) {
setState(() {
title = value;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
PopupMenuButton<String>(
onSelected: _select,
itemBuilder: (BuildContext context) {
return _getItemBuilder();
},
)
],
),
),
);
}
// List<PopupMenuEntry> _getItemBuilder() {
// List<PopupMenuEntry> list = List();
// list.add(PopupMenuItem(
// child: Text("白天模式"),
// value: "Day",
// ));
// list.add(PopupMenuItem(
// child: Text("黑夜模式"),
// value: "Night",
// ));
// return list;
// }
}
ButtonBar
水平排列的按鈕組
const ButtonBar({
Key key,
//子組件的間隔樣式
this.alignment = MainAxisAlignment.end,
this.mainAxisSize = MainAxisSize.max,
//子children
this.children = const <Widget>[],
})
MainAxisAlignment,之間的博客中講過客年。
class FlutterButtonBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ButtonBar(children: <Widget>[
Text("ButtonBar0"),
Icon(Icons.ac_unit),
Text("ButtonBar1")
], );
}
}
到這里霞幅,終于把Material Style的大部分Button講完了,開始下一個量瓜。
本地代碼地址
Flutter 豆瓣客戶端司恳,誠心開源
Flutter Container
Flutter SafeArea
Flutter Row Column MainAxisAlignment Expanded
Flutter Image全解析
Flutter 常用按鈕總結(jié)
Flutter ListView豆瓣電影排行榜
Flutter Card
Flutter Navigator&Router(導(dǎo)航與路由)
OverscrollNotification不起效果引起的Flutter感悟分享
Flutter 上拉抽屜實現(xiàn)
Flutter 豆瓣客戶端,誠心開源
Flutter 更改狀態(tài)欄顏色