延續(xù)上一節(jié)的內(nèi)容死宣,上一節(jié)我們講解了各種Dialog跟提示,其中包括輕量級(jí)跟非輕量級(jí)碴开,我們了解到了像
SnackBar毅该、Tooltip博秫、Dialog
等各種具有提示交互作用的Widget,今天我們繼續(xù)上一篇的內(nèi)容眶掌,來一塊了解一下各種用于進(jìn)度顯示的Widget跟checkBox
等選擇作用的Widget台盯。
今天我們來一塊了解一下各種Index跟Chose控件,像CircularProgressIndicator
圓環(huán)進(jìn)度條畏线,
LinearProgressIndicator
水平進(jìn)度條静盅,Slider
滑桿,還有Checkbox寝殴,Switch等蒿叠,下面我們就一塊來進(jìn)入今天的分享。
1. CircularProgressIndicator
老規(guī)矩蚣常,先從構(gòu)造方法入手
const CircularProgressIndicator({
Key key,
double value, //進(jìn)度(0-1)之間市咽,不設(shè)置進(jìn)度會(huì)一直循環(huán)
Color backgroundColor,
Animation<Color> valueColor, //圓環(huán)進(jìn)度顏色
this.strokeWidth = 4.0, //圓環(huán)進(jìn)度條寬度
String semanticsLabel,
String semanticsValue,
})
從上述CircularProgressIndicator
的方法簽名中,我們首先可以得到的信息是抵蚊,圓環(huán)進(jìn)度條可以自定義指定背景顏色跟寬度施绎,可以設(shè)置進(jìn)度,我貼上幾個(gè)簡單的例子來直觀體驗(yàn)一下贞绳。
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: new Column(
children: <Widget>[
SizedBox(height: 30.0),
Text("設(shè)置進(jìn)度比為80%(0.8)"),
SizedBox(height: 30.0),
CircularProgressIndicator(
value: 0.8, //
backgroundColor: Colors.green,
strokeWidth: 10.0,
),
SizedBox(height: 30.0), //設(shè)置間隔
Text("未做任何處理谷醉,默認(rèn)一直循環(huán)"),
CircularProgressIndicator(),
Text("設(shè)置圓環(huán)進(jìn)度顏色為紅色"),
CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.deepOrange),
),
],
)),
);
}
}
//const CircularProgressIndicator({
//Key key,
//double value, //進(jìn)度(0-1)之間,不設(shè)置進(jìn)度會(huì)一直循環(huán)
//Color backgroundColor,
//Animation<Color> valueColor, //圓環(huán)進(jìn)度顏色
//this.strokeWidth = 4.0, //圓環(huán)進(jìn)度條寬度
//String semanticsLabel,
//String semanticsValue,
//})
效果圖
2.LinearProgressIndicator
對比LinearProgressIndicator
的構(gòu)造方法
const LinearProgressIndicator({
Key key,
double value,
Color backgroundColor,
Animation<Color> valueColor,
String semanticsLabel,
String semanticsValue,
})
我們發(fā)現(xiàn)LinearProgressIndicator
與CircularProgressIndicator
除了少了一個(gè)strokeWidth不支持設(shè)置進(jìn)度條寬度之外冈闭,其他完全一致俱尼,所以我就不多做講解了,直接看下效果吧萎攒。
效果圖
樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: new Column(
children: <Widget>[
SizedBox(height: 30.0),
Text("設(shè)置進(jìn)度比為80%(0.8)"),
SizedBox(height: 30.0),
LinearProgressIndicator(
value: 0.8, //
backgroundColor: Colors.green,
),
SizedBox(height: 30.0), //設(shè)置間隔
Text("未做任何處理遇八,默認(rèn)一直循環(huán)"),
LinearProgressIndicator(),
Text("設(shè)置進(jìn)度顏色為紅色,背景透明"),
LinearProgressIndicator(
backgroundColor: Colors.transparent,
valueColor: AlwaysStoppedAnimation(Colors.deepOrange),
),
],
)),
);
}
}
3.Slider
構(gòu)造方法
const Slider({
Key key,
@required this.value,//滑塊的值
@required this.onChanged, //改變時(shí)觸發(fā)。
this.onChangeStart, //改變前觸發(fā)耍休。
this.onChangeEnd, //改變后觸發(fā)刃永。
this.min = 0.0, //用戶可以選擇的最小值。
this.max = 1.0, //用戶可以選擇的最大值羊精。
this.divisions, //離散部分的數(shù)量
this.label, //滑塊處于活動(dòng)狀態(tài)時(shí)顯示在滑塊上方的標(biāo)簽斯够。
this.activeColor,//激活時(shí)的顏色
this.inactiveColor,//滑塊軌道的非活動(dòng)部分的顏色。
this.semanticFormatterCallback,
})
Slider
滑桿進(jìn)度條园匹,支持用戶手動(dòng)拖拽定位雳刺,如果不涉及到用戶拖拽交互劫灶,我們可以把他認(rèn)為就是一個(gè)靜態(tài)的LinearProgressIndicator
裸违,使用起來也比較簡單。但是如果需用跟用戶交互本昏,涉及到用戶的拖拽手勢然后動(dòng)態(tài)的改變Slider的值供汛,就需要借助我們之前講到的StatefullWidget
,通過setState
來完成用戶交互的數(shù)據(jù)重新更新渲染到Slider上,我們來一起體驗(yàn)一下怔昨。
3.1 靜態(tài)Slider
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: new Slider(
value: 0.4,
onChanged: null,
),
),
);
}
}
效果圖
如上圖雀久,就僅僅只是一個(gè)指示作用,不支持用戶手指拖拽滑動(dòng)趁舀,下面我們來借助StatefullWidget來做一下簡單交互赖捌。
3.2 動(dòng)態(tài)Slider
我們來模擬一下用戶拖拽Slider可以設(shè)置當(dāng)前是星期幾的效果。
效果圖
這里提到一個(gè)小細(xì)節(jié)矮烹,有讀者給我反饋說
在使用Slider的時(shí)候越庇,在Slider上方的label一直不顯示
,這里是因?yàn)閘abel在指定了divisions
也就是指定當(dāng)前進(jìn)度被離散成多少份之后才會(huì)顯示奉狈,讀者注意到這個(gè)細(xì)節(jié)即可卤唉。下面是上圖的樣例代碼,供大家參考仁期。
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => SliderState();
}
class SliderState extends State {
double _currentIndex = 0.0;
void _onSliderStateChanged(double value) {
setState(() {
_currentIndex = value;
print(_currentIndex.toString() + '-------------------');
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: new Slider(
value: _currentIndex,
label: '星期${(_currentIndex*10).floor().toString()}',
activeColor: Colors.redAccent,
inactiveColor: Colors.grey,
max: 0.7,
min: 0.0,
onChanged: _onSliderStateChanged,
onChangeStart: (value){
print('開始滑動(dòng)-------------$value');
},
onChangeEnd: (value){
print('結(jié)束滑動(dòng)-------------$value');
},
divisions: 7,
),
),
);
}
}
//
//const Slider({
//Key key,
//@required this.value,滑塊的值
//@required this.onChanged, //改變時(shí)觸發(fā)桑驱。
//this.onChangeStart, //改變前觸發(fā)。
//this.onChangeEnd, //改變后觸發(fā)跛蛋。
//this.min = 0.0, //用戶可以選擇的最小值熬的。
//this.max = 1.0, //用戶可以選擇的最大值。
//this.divisions, //離散部分的數(shù)量
//this.label, //滑塊處于活動(dòng)狀態(tài)時(shí)顯示在滑塊上方的標(biāo)簽赊级。
//this.activeColor,//激活時(shí)的顏色
//this.inactiveColor,//滑塊軌道的非活動(dòng)部分的顏色悦析。
//this.semanticFormatterCallback,
//})
上面說完了常用的進(jìn)度展示控件,我們通過上面的學(xué)習(xí)基本能處理業(yè)務(wù)上不同場景下如果選用進(jìn)度Widget此衅,下面我們來進(jìn)入本篇的第二部分强戴,關(guān)于Chose控件的介紹。
4.Checkbox
Checkbox
跟Slider一樣挡鞍,因?yàn)樾枰幚砘蛘哒f需要記錄用戶的選擇狀態(tài)骑歹,然后去更新Checkbox
的選中狀態(tài),所以理所當(dāng)然我們也需要使用StatefullWidget
來完成這一操作墨微。否則Checkbox
只能跟上面分析Slider
一樣道媚,只能一個(gè)靜態(tài)展示,不能完成或者說記錄用戶的行為操作翘县。
Checkbox使用跟原生Android一樣最域,沒有什么需要特別注意的知識(shí)點(diǎn),我就不多做講解了锈麸,下面我們一起來看一個(gè)例子镀脂。
樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => SliderState();
}
class SliderState extends State {
bool isChecked = false;
void _onCheckStateChanged(bool value) {
setState(() {
isChecked = value;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: new Checkbox(
value: isChecked,
onChanged: _onCheckStateChanged,
activeColor: Colors.green,
),
),
);
}
}
5.Switch
Switch
跟Checkbox
用戶上類似,都是為了記錄用戶的選中狀態(tài)忘伞,只不過是Switch
可定制的部分比Checkbox
更多一些薄翅,開發(fā)者可以加入更多的個(gè)性化定制沙兰,我們還是先從構(gòu)造方法說起。
const Switch({
Key key,
@required this.value,//切換按鈕的值翘魄。
@required this.onChanged,//改變時(shí)觸發(fā)鼎天。
this.activeColor, //激活時(shí)圓點(diǎn)的顏色。
this.activeTrackColor, //激活時(shí)橫條的顏色
this.inactiveThumbColor,//非激活時(shí)原點(diǎn)的顏色暑竟。
this.inactiveTrackColor, // 非激活時(shí)原點(diǎn)的顏色斋射。
this.activeThumbImage, //圓點(diǎn)還支持圖片,激活時(shí)的效果
this.inactiveThumbImage,//非激活原點(diǎn)的圖片效果但荤。
this.materialTapTargetSize,
})
下面我把幾個(gè)配置不同樣式的Switch效果圖貼上了绩鸣,讀者可根據(jù)代碼自行分析其具體實(shí)現(xiàn)細(xì)節(jié),我就不逐一講解構(gòu)造方法中各個(gè)屬性的作用了纱兑。
效果圖
這里說明一下呀闻,上圖為什么點(diǎn)擊其中一個(gè)
Switch
另外兩個(gè)也會(huì)跟著聯(lián)動(dòng),原因是我在寫測試代碼的時(shí)候潜慎,為了減少代碼的書寫量捡多,盡可能的讓代碼清晰,所以給三個(gè)Switch
在onChanged
的時(shí)候綁定的是同一個(gè)函數(shù)回調(diào)铐炫,沒有分開單獨(dú)處理每個(gè)Swtich
的回調(diào)事件垒手,讀者知道即可,不用過于糾結(jié)倒信。
如上圖:
第一個(gè)Switch我指定了科贬,激活跟非激活狀態(tài)的圓點(diǎn)顏色跟滑動(dòng)軌跡的顏色
第二個(gè)Switch我指定了,激活跟非激活狀態(tài)下圓點(diǎn)是資源圖片鳖悠。
第三個(gè)Swtich沒有做任何處理榜掌。
上述效果圖代碼如下:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => SliderState();
}
class SliderState extends State {
bool isChecked = false;
void _onCheckStateChanged(bool value) {
setState(() {
isChecked = value;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: Column(
children: <Widget>[
new Switch(
value: isChecked,
inactiveThumbColor: Colors.redAccent,
inactiveTrackColor: Colors.brown,
activeTrackColor: Colors.blue,
onChanged: _onCheckStateChanged,
activeColor: Colors.green,
),
Text("指定激活跟非激活狀態(tài)下,圓點(diǎn)都為圖片"),
new Switch(
value: isChecked,
inactiveThumbImage: AssetImage('images/a.png'),
activeThumbImage: AssetImage('images/aaa.png'),
onChanged: _onCheckStateChanged,
activeColor: Colors.green,
),
new Switch(
value: isChecked,
onChanged: _onCheckStateChanged,
)
],
),
),
);
}
}
//
//const Switch({
//Key key,
//@required this.value,//切換按鈕的值乘综。
//@required this.onChanged,//改變時(shí)觸發(fā)憎账。
//this.activeColor, //激活時(shí)圓點(diǎn)的顏色。
//this.activeTrackColor, //激活時(shí)橫條的顏色
//this.inactiveThumbColor,//非激活時(shí)原點(diǎn)的顏色卡辰。
//this.inactiveTrackColor, // 非激活時(shí)原點(diǎn)的顏色胞皱。
//this.activeThumbImage, //圓點(diǎn)還支持圖片,激活時(shí)的效果
//this.inactiveThumbImage,//非激活原點(diǎn)的圖片效果九妈。
//this.materialTapTargetSize,
//})
屬性及外觀
Switch和Checkbox屬性比較簡單反砌,讀者可以查看API文檔,它們都有一個(gè)activeColor屬性萌朱,用于設(shè)置激活態(tài)的顏色宴树。至于大小,
到目前為止嚷兔,Checkbox的大小是固定的森渐,無法自定義,而Switch只能定義寬度冒晰,高度也是固定的同衣。
值得一提的是Checkbox有一個(gè)屬性tristate ,表示是否為三態(tài)壶运,其默認(rèn)值為false 耐齐,這時(shí)Checkbox有兩種狀態(tài)即“選中”和“不選中”,對應(yīng)的value值為true和false 蒋情;如果其值為true時(shí)埠况,value的值會(huì)增加一個(gè)狀態(tài)null,讀者可以自行了解棵癣。
6.Radio
在項(xiàng)目開發(fā)或者真實(shí)案例中Radio通常都是成組出現(xiàn)辕翰,比如性別選擇、愛好選擇等等場景中狈谊,F(xiàn)lutter充分考慮到了這一場景需求喜命,給我們提供了便捷使用Radio的API。利用flutter的Radio能滿足我們在原生Android中各個(gè)使用Radio的場景河劝。下面我們來一起看下構(gòu)造方法壁榕,順便有一點(diǎn)小細(xì)節(jié)需要講解一下。
const Radio({
Key key,
@required this.value, //單選的值赎瞎。
@required this.groupValue, //選擇組的值牌里。
@required this.onChanged, //改變時(shí)觸發(fā)。
this.activeColor, //激活時(shí)的顏色
this.materialTapTargetSize,
})
看下Radio中的這段代碼
/// The value represented by this radio button.
final T value;
/// The currently selected value for this group of radio buttons.
///
/// This radio button is considered selected if its [value] matches the
/// [groupValue].
final T groupValue;
從Radio的這段源碼注釋中我們可以看到Radio
在處理分組時(shí)务甥,value
跟groupValue
是作為一個(gè)泛型參數(shù)牡辽,也就是說我們可以指定value的類型為int、或者String等類型敞临,并且當(dāng)value和groupValue一致的時(shí)候則選中
根據(jù)這些我們就可以自由發(fā)揮去處理我們實(shí)際開發(fā)中需要使用Radio
分組的業(yè)務(wù)邏輯了催享。下面我貼上一個(gè)選擇性別
跟選擇數(shù)字
的樣例代碼供大家參考,讀者可結(jié)合上述關(guān)于Radio的源碼
分析和下面的代碼對比學(xué)習(xí)哟绊。
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FlutterDemo()));
}
class FlutterDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => SliderState();
}
class SliderState extends State {
int _value = 0;
String _sex = '男';
void _onRadioChanged(int value) {
setState(() {
_value = value;
});
}
void _onSexRadioChanged(String value) {
setState(() {
_sex = value;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter進(jìn)階之旅"),
),
body: new Center(
child: Column(children: <Widget>[
Radio(
value: 0,
groupValue: _value,
onChanged: _onRadioChanged,
),
Radio(
value: 1,
groupValue: _value,
onChanged: _onRadioChanged,
),
Radio(
value: 2,
groupValue: _value,
onChanged: _onRadioChanged,
),
Text("選擇的數(shù)字為$_value"),
SizedBox(height: 50.0),
Text("選擇性別"),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Radio(
value: '男',
groupValue: _sex,
onChanged: _onSexRadioChanged,
),
Radio(
value: '女',
groupValue: _sex,
onChanged: _onSexRadioChanged,
),
],
),
Text(_sex),
]),
),
);
}
}
//當(dāng)value和groupValue一致的時(shí)候則選中
//const Radio({
//Key key,
//@required this.value, //單選的值因妙。
//@required this.groupValue, //選擇組的值。
//@required this.onChanged, //改變時(shí)觸發(fā)票髓。
//this.activeColor, //激活時(shí)的顏色
//this.materialTapTargetSize,
//})
效果圖