大家好,今天使用到的有TextEditingController、TextField、InputDecoration、CircularProgressIndicator、AlwaysStoppedAnimation
,也會用到先前介紹的Ink、InkWell
CircularProgressIndicator and LinearProgressIndicator (Flutter Widget of the Week)
3.7 输入框及表单
我們要給圖片加上波紋的特效,找到Ink裡面有一個直接使用圖片背景方法,Ink.image
但是因為沒找到給他做圓角的方法,所以還是用先前用的方法,
//源碼註解說,假如圖片上不會在渲染東西,如沒有波紋的話,推薦使用Container、BoxDecoration
Ink.image()
_buildUserAvatar() {
return Stack(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0), //Ink圓角
image: DecorationImage(
image: AssetImage(
widget.user.assetName,
),
)),
width: screenSized.width * 0.3,
height: screenSized.width * .3,
child: InkWell(
borderRadius: BorderRadius.circular(8.0),//InkWell 波紋圓角
onTap: () {},
),
),
),
Positioned(
right: 0.0,
bottom: 0.0,
child: Icon(Icons.edit),
)
],
);
}
文字輸入用Container幫輸入框做灰底背景,
使用TextField時可以用InputDecoration
,他可以設置輸入框的外觀,提示文字、背景、邊框、錯誤提示等等
const InputDecoration({
this.icon,
this.labelText,
this.labelStyle,
this.helperText,
this.helperStyle,
this.helperMaxLines,
this.hintText,
this.hintStyle,
this.hintMaxLines,
this.errorText,
this.errorStyle,
this.errorMaxLines,
@Deprecated(
'Use floatingLabelBehavior instead. '
'This feature was deprecated after v1.13.2.'
)
這邊要設置的是border邊框,InputBorder.none
無邊框
TextField設置cursorColor
,輸入框光標的顏色
_buildInputTextField() {
return Container(
margin: EdgeInsets.all(16.0),
padding: EdgeInsets.symmetric(horizontal: 16.0),
color: Color(0xff333333),
width: screenSized.width * 0.7,
child: TextField(
controller: _editingController,
cursorColor: Colors.white,
style: inputStyle,
decoration:
InputDecoration(border: InputBorder.none),
),
);
}
設置初始文字或要監聽文字的改變,使用controller
在initState實例controller的時候帶入初始文本
從前面傳進來的文字
@override
void initState() {
_editingController = TextEditingController(text: widget.user.name);
_editingController.addListener(() {
print(_editingController.text);
});
super.initState();
}
/// Create a simple text button.
右上方有一個儲存按鍵,被點擊的時候會變另一種顏色,所以我們可以使用FlatButton
大部分的Button都可以設定好幾種狀態的顏色,例如:highlightColor、hoverColor、splashColor
這邊我們要設的是disabledTextColor、textColor
FlatButton判斷是不是disabled,主要是看onPressed是不是帶null
,所以一開始設一個boolean判斷現在是否可以點擊
bool _isButtonDisabled = false;
FlatButton(
textColor: saveStyle.color,
disabledTextColor: Colors.grey,
padding: EdgeInsets.zero,//預設有padding,所以用`EdgeInsets.zero`
child: Text("儲存",),
onPressed: _isButtonDisabled ? null : _saveChange,
),
點擊執行_saveChange
更新user.name
變更狀態,並setState
兩秒後返回前一頁
void _saveChange() {
widget.user.name = _editingController.text;
print("widget.user.name ${widget.user.name}");
savingState = true; //用在offstage顯示Loading的動畫
setState(() {});
//假設這邊跟雲端聯繫,要顯示Loading,兩秒後,返回結果,回前一頁
Future.delayed(Duration(seconds: 2), () {
savingState = false;
setState(() {
Navigator.of(context).pop(1);
});
});
}
Offstage用法在前一篇說過,當savingState為真時,顯示動畫,否則隱藏
CircularProgressIndicator
,什麼都不設置就是一個轉圈圈的動畫,
當然也可以設定value,backgroundColor什麼的,這邊只想改變它的顏色valueColor
Animation<Color>
需要輸入Animation給它
如果不想顏色變來變去時直接使用AlwaysStoppedAnimation<Color>(color)
Offstage(
offstage: !savingState,
child: Container(
color: Colors.black.withOpacity(0.5),
child: Center(
child: SizedBox(
width: 50.0,
height: 50.0,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.red),
),
),
),
),
)
最後在更新前一頁畫面即可,在前一頁選擇使用者頁面,推進頁面的地方加上.then((value){})
Navigator.of(context).push(...略過部分code...).then((value){});
value是按返回時傳回來的值,判斷值是否等於1,是的話就更新畫面
onTap: () {
//這是在選這使用者頁面,前一篇的
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => editMode? EditUserPage(user: user,): MainPage()))
.then((value) {
if (value == 1) {
setState(() {});
} else {
print("未儲存變更");
}
});
},
今日之效果圖
GitHub連結: flutter-netflix-clone