2019/12/5 早9點(diǎn)
Flutter - 創(chuàng)建一個(gè)底部彈窗
1.思路
- 創(chuàng)建一個(gè)
Widget并且定位到屏幕下方:使用Stack+Positioned實(shí)現(xiàn) - 這個(gè)
Widget具有縱向平移功能:使用SlideTransition實(shí)現(xiàn) - 動(dòng)畫的實(shí)現(xiàn):設(shè)置
AnimationController以及Tween<Offset>
2.實(shí)現(xiàn)
對(duì)著思路倒著來。
2.1 AnimationController以及Tween<Offset>
新建一個(gè)StatefulWidget并且初始化AnimationController
AnimationController controller;
@override
void initState() {
// TODO: implement initState
super.initState();
controller = new AnimationController(
duration: Duration(milliseconds: 200), vsync: this);
}
因?yàn)槭菑钠聊坏撞繌棾觯詫?duì)應(yīng)的平移描述Tween<Offset>如下:
Tween<Offset> tween;
tween = Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset(0.0, 0.0),
);
注意,這里的Offset描述規(guī)則是:
- 起始位置begin - x方向不平移,y方向(由屏幕
(0,0)向下為正)處于平移一個(gè)Widget高度的位置 - 結(jié)束位置end - x方向不平移,y方向不平移原始位置
所以這個(gè)Tween描述的就是從下向上移動(dòng)
所以controller控制彈窗的彈出與收回就是對(duì)動(dòng)畫的順序與逆序播放:
if (widget.show) {
controller.forward();
} else {
controller.reverse();
}
2.2 SlideTransition
SlideTransition是一個(gè)動(dòng)畫的封裝類,兩個(gè)參數(shù)分別為:Animation<Offset>和Widget:
SlideTransition(
position: tween.animate(controller),
child: childWidget,
)
然后在Widget內(nèi)部設(shè)置一個(gè)flag,用于描述彈窗的彈出與收回,并且將其暴露給外部即可。
2.3 可以滑動(dòng)的Widget
class SlideWidget extends StatefulWidget {
final bool show;
final Widget child;
SlideWidget({
@required this.show,
@required this.child,
});
@override
_ChapterAppbarViewState createState() => new _ChapterAppbarViewState();
}
class _SlideWidgetState extends State<SlideWidget>
with TickerProviderStateMixin {
AnimationController controller;
Tween<Offset> tween;
@override
void initState() {
super.initState();
controller = new AnimationController(
duration: Duration(milliseconds: 200), vsync: this);
tween = Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset(0.0, 0.0),
);
}
@override
Widget build(BuildContext context) {
if (widget.show) {
controller.forward();
} else {
controller.reverse();
}
Size screenSize = MediaQuery.of(context).size;
double screenWidth = screenSize.width;
return SlideTransition(
position: tween.animate(controller),
child: widget.child,
);
}
}
2.4 Stack + Positioned
最后一步,把這個(gè)Widget放置在屏幕下側(cè)就好:
Stack(
children: <Widget>[
...
Positioned(
child: SlideWidget(
show: needShow,
child: buildDialog,
),
bottom: 0.0,
left: 0.0,
),
],
),
添加點(diǎn)擊事件修改SlideWidget的show屬性并且刷新就可以實(shí)現(xiàn)平移了。