2019/12/5 早9点
Flutter - 创建一个底部弹窗
1.思路
- 创建一个
Widget
并且定位到屏幕下方:使用Stack
+Positioned
实现 - 这个
Widget
具有纵向平移功能:使用SlideTransition
实现 - 动画的实现:设置
AnimationController
以及Tween<Offset>
2.实现
对着思路倒着来。
2.1 AnimationController
以及Tween<Offset>
新建一个StatefulWidget
并且初始化AnimationController
AnimationController controller;
@override
void initState() {
// TODO: implement initState
super.initState();
controller = new AnimationController(
duration: Duration(milliseconds: 200), vsync: this);
}
因为是从屏幕底部弹出,所以对应的平移描述Tween<Offset>
如下:
Tween<Offset> tween;
tween = Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset(0.0, 0.0),
);
注意,这里的Offset
描述规则是:
- 起始位置begin - x方向不平移,y方向(由屏幕
(0,0)
向下为正)处于平移一个Widget
高度的位置 - 结束位置end - x方向不平移,y方向不平移原始位置
所以这个Tween
描述的就是从下向上移动
所以controller
控制弹窗的弹出与收回就是对动画的顺序与逆序播放:
if (widget.show) {
controller.forward();
} else {
controller.reverse();
}
2.2 SlideTransition
SlideTransition
是一个动画的封装类,两个参数分别为:Animation<Offset>
和Widget
:
SlideTransition(
position: tween.animate(controller),
child: childWidget,
)
然后在Widget
内部设置一个flag,用于描述弹窗的弹出与收回,并且将其暴露给外部即可。
2.3 可以滑动的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
最后一步,把这个Widget
放置在屏幕下侧就好:
Stack(
children: <Widget>[
...
Positioned(
child: SlideWidget(
show: needShow,
child: buildDialog,
),
bottom: 0.0,
left: 0.0,
),
],
),
添加点击事件修改SlideWidget
的show
属性并且刷新就可以实现平移了。