延續上一節的內容,上一節咱們講解了各類Dialog跟提示,其中包括輕量級跟非輕量級,咱們瞭解到了像
SnackBar、Tooltip、Dialog
等各類具備提示交互做用的Widget,今天咱們繼續上一篇的內容,來一塊瞭解一下各類用於進度顯示的Widget跟checkBox
等選擇做用的Widget。java
今天咱們來一塊瞭解一下各類Index跟Chose控件,像CircularProgressIndicator
圓環進度條, LinearProgressIndicator
水平進度條,Slider
滑桿,還有Checkbox,Switch等,下面咱們就一塊來進入今天的分享。app
老規矩,先從構造方法入手less
const CircularProgressIndicator({ Key key, double value, //進度(0-1)之間,不設置進度會一直循環 Color backgroundColor, Animation<Color> valueColor, //圓環進度顏色 this.strokeWidth = 4.0, //圓環進度條寬度 String semanticsLabel, String semanticsValue, }) 複製代碼
從上述CircularProgressIndicator
的方法簽名中,咱們首先能夠獲得的信息是,圓環進度條能夠自定義指定背景顏色跟寬度,能夠設置進度,我貼上幾個簡單的例子來直觀體驗一下。ide
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進階之旅"),
),
body: new Center(
child: new Column(
children: <Widget>[
SizedBox(height: 30.0),
Text("設置進度比爲80%(0.8)"),
SizedBox(height: 30.0),
CircularProgressIndicator(
value: 0.8, //
backgroundColor: Colors.green,
strokeWidth: 10.0,
),
SizedBox(height: 30.0), //設置間隔
Text("未作任何處理,默認一直循環"),
CircularProgressIndicator(),
Text("設置圓環進度顏色爲紅色"),
CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.deepOrange),
),
],
)),
);
}
}
//const CircularProgressIndicator({
//Key key,
//double value, //進度(0-1)之間,不設置進度會一直循環
//Color backgroundColor,
//Animation<Color> valueColor, //圓環進度顏色
//this.strokeWidth = 4.0, //圓環進度條寬度
//String semanticsLabel,
//String semanticsValue,
//})
複製代碼
效果圖 函數
對比LinearProgressIndicator
的構造方法學習
const LinearProgressIndicator({ Key key, double value, Color backgroundColor, Animation<Color> valueColor, String semanticsLabel, String semanticsValue, }) 複製代碼
咱們發現LinearProgressIndicator
與CircularProgressIndicator
除了少了一個strokeWidth不支持設置進度條寬度以外,其餘徹底一致,因此我就很少作講解了,直接看下效果吧。測試
效果圖 ui
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進階之旅"),
),
body: new Center(
child: new Column(
children: <Widget>[
SizedBox(height: 30.0),
Text("設置進度比爲80%(0.8)"),
SizedBox(height: 30.0),
LinearProgressIndicator(
value: 0.8, //
backgroundColor: Colors.green,
),
SizedBox(height: 30.0), //設置間隔
Text("未作任何處理,默認一直循環"),
LinearProgressIndicator(),
Text("設置進度顏色爲紅色,背景透明"),
LinearProgressIndicator(
backgroundColor: Colors.transparent,
valueColor: AlwaysStoppedAnimation(Colors.deepOrange),
),
],
)),
);
}
}
複製代碼
構造方法this
const Slider({ Key key, @required this.value,//滑塊的值 @required this.onChanged, //改變時觸發。 this.onChangeStart, //改變前觸發。 this.onChangeEnd, //改變後觸發。 this.min = 0.0, //用戶能夠選擇的最小值。 this.max = 1.0, //用戶能夠選擇的最大值。 this.divisions, //離散部分的數量 this.label, //滑塊處於活動狀態時顯示在滑塊上方的標籤。 this.activeColor,//激活時的顏色 this.inactiveColor,//滑塊軌道的非活動部分的顏色。 this.semanticFormatterCallback, }) 複製代碼
Slider
滑桿進度條,支持用戶手動拖拽定位,若是不涉及到用戶拖拽交互,咱們能夠把他認爲就是一個靜態的LinearProgressIndicator
,使用起來也比較簡單。可是若是需用跟用戶交互,涉及到用戶的拖拽手勢而後動態的改變Slider的值,就須要藉助咱們以前講到的StatefullWidget
,經過setState
來完成用戶交互的數據從新更新渲染到Slider上,咱們來一塊兒體驗一下。spa
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進階之旅"),
),
body: new Center(
child: new Slider(
value: 0.4,
onChanged: null,
),
),
);
}
}
複製代碼
效果圖
咱們來模擬一下用戶拖拽Slider能夠設置當前是星期幾的效果。 效果圖
在使用Slider的時候,在Slider上方的label一直不顯示
,這裏是由於label在指定了
divisions
也就是指定當前進度被離散成多少份以後纔會顯示,讀者注意到這個細節便可。下面是上圖的樣例代碼,供你們參考。
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進階之旅"),
),
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('開始滑動-------------$value');
},
onChangeEnd: (value){
print('結束滑動-------------$value');
},
divisions: 7,
),
),
);
}
}
//
//const Slider({
//Key key,
//@required this.value,滑塊的值
//@required this.onChanged, //改變時觸發。
//this.onChangeStart, //改變前觸發。
//this.onChangeEnd, //改變後觸發。
//this.min = 0.0, //用戶能夠選擇的最小值。
//this.max = 1.0, //用戶能夠選擇的最大值。
//this.divisions, //離散部分的數量
//this.label, //滑塊處於活動狀態時顯示在滑塊上方的標籤。
//this.activeColor,//激活時的顏色
//this.inactiveColor,//滑塊軌道的非活動部分的顏色。
//this.semanticFormatterCallback,
//})
複製代碼
上面說完了經常使用的進度展現控件,咱們經過上面的學習基本能處理業務上不一樣場景下若是選用進度Widget,下面咱們來進入本篇的第二部分,關於Chose控件的介紹。
Checkbox
跟Slider同樣,由於須要處理或者說須要記錄用戶的選擇狀態,而後去更新Checkbox
的選中狀態,因此理所固然咱們也須要使用StatefullWidget
來完成這一操做。不然Checkbox
只能跟上面分析Slider
同樣,只能一個靜態展現,不能完成或者說記錄用戶的行爲操做。
Checkbox使用跟原生Android同樣,沒有什麼須要特別注意的知識點,我就很少作講解了,下面咱們一塊兒來看一個例子。
樣例代碼
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進階之旅"),
),
body: new Center(
child: new Checkbox(
value: isChecked,
onChanged: _onCheckStateChanged,
activeColor: Colors.green,
),
),
);
}
}
複製代碼
Switch
跟Checkbox
用戶上相似,都是爲了記錄用戶的選中狀態,只不過是Switch
可定製的部分比Checkbox
更多一些,開發者能夠加入更多的個性化定製,咱們仍是先從構造方法提及。
const Switch({ Key key, @required this.value,//切換按鈕的值。 @required this.onChanged,//改變時觸發。 this.activeColor, //激活時圓點的顏色。 this.activeTrackColor, //激活時橫條的顏色 this.inactiveThumbColor,//非激活時原點的顏色。 this.inactiveTrackColor, // 非激活時原點的顏色。 this.activeThumbImage, //圓點還支持圖片,激活時的效果 this.inactiveThumbImage,//非激活原點的圖片效果。 this.materialTapTargetSize, }) 複製代碼
下面我把幾個配置不一樣樣式的Switch效果圖貼上了,讀者可根據代碼自行分析其具體實現細節,我就不逐一講解構造方法中各個屬性的做用了。
效果圖
這裏說明一下,上圖爲何點擊其中一個
Switch
另外兩個也會跟着聯動,緣由是我在寫測試代碼的時候,爲了減小代碼的書寫量,儘量的讓代碼清晰,因此給三個Switch
在onChanged
的時候綁定的是同一個函數回調,沒有分開單獨處理每一個Swtich
的回調事件,讀者知道便可,不用過於糾結。
如上圖: 第一個Switch我指定了,激活跟非激活狀態的圓點顏色跟滑動軌跡的顏色 第二個Switch我指定了,激活跟非激活狀態下圓點是資源圖片。 第三個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進階之旅"),
),
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("指定激活跟非激活狀態下,圓點都爲圖片"),
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,//改變時觸發。
//this.activeColor, //激活時圓點的顏色。
//this.activeTrackColor, //激活時橫條的顏色
//this.inactiveThumbColor,//非激活時原點的顏色。
//this.inactiveTrackColor, // 非激活時原點的顏色。
//this.activeThumbImage, //圓點還支持圖片,激活時的效果
//this.inactiveThumbImage,//非激活原點的圖片效果。
//this.materialTapTargetSize,
//})
複製代碼
在項目開發或者真實案例中Radio一般都是成組出現,好比性別選擇、愛好選擇等等場景中,Flutter充分考慮到了這一場景需求,給咱們提供了便捷使用Radio的API。利用flutter的Radio能知足咱們在原生Android中各個使用Radio的場景。下面咱們來一塊兒看下構造方法,順便有一點小細節須要講解一下。
const Radio({ Key key, @required this.value, //單選的值。 @required this.groupValue, //選擇組的值。 @required this.onChanged, //改變時觸發。 this.activeColor, //激活時的顏色 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
在處理分組時,value
跟groupValue
是做爲一個泛型參數,也就是說咱們能夠指定value的類型爲int、或者String等類型,而且當value和groupValue一致的時候則選中
根據這些咱們就能夠自由發揮去處理咱們實際開發中須要使用Radio
分組的業務邏輯了。下面我貼上一個選擇性別
跟選擇數字
的樣例代碼供你們參考,讀者可結合上述關於Radio的源碼
分析和下面的代碼對比學習。
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進階之旅"),
),
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("選擇的數字爲$_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),
]),
),
);
}
}
//當value和groupValue一致的時候則選中
//const Radio({
//Key key,
//@required this.value, //單選的值。
//@required this.groupValue, //選擇組的值。
//@required this.onChanged, //改變時觸發。
//this.activeColor, //激活時的顏色
//this.materialTapTargetSize,
//})
複製代碼
效果圖