gpt4 book ai didi

dart - 如何使用 flutter 创建自定义弹出菜单

转载 作者:IT老高 更新时间:2023-10-28 12:37:32 27 4
gpt4 key购买 nike

我想在单击应用栏上的按钮时创建一个弹出菜单.. 我希望出现这样的东西:

enter image description here

有没有办法在 flutter 中做到这一点?包什么的?

最佳答案

我试过了,但我在以这种方式显示子小部件时遇到了一些问题。所以,这里有两个解决方案:

class TestScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> with SingleTickerProviderStateMixin {
AnimationController animationController;
bool _menuShown = false;

@override
void initState() {
animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500));
super.initState();
}

@override
Widget build(BuildContext context) {
Animation opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(animationController);
if (_menuShown)
animationController.forward();
else
animationController.reverse();
return Scaffold(
appBar: AppBar(
actions: <Widget>[IconButton(icon: Icon(Icons.menu), onPressed: (){
setState(() {
_menuShown = !_menuShown;
});
})],
),
body: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
child: FadeTransition(
opacity: opacityAnimation,
child: _ShapedWidget(),
),
right: 4.0,
top: 16.0,
),
],
),
);
}
}

class _ShapedWidget extends StatelessWidget {
_ShapedWidget();
final double padding = 4.0;

@override
Widget build(BuildContext context) {
return Center(
child: Material(
clipBehavior: Clip.antiAlias,
shape:
_ShapedWidgetBorder(borderRadius: BorderRadius.all(Radius.circular(padding)), padding: padding),
elevation: 4.0,
child: Container(
padding: EdgeInsets.all(padding).copyWith(bottom: padding * 2),
child: SizedBox(width: 150.0, height: 250.0, child: Center(child: Text('ShapedWidget'),),),
)),
);
}
}

class _ShapedWidgetBorder extends RoundedRectangleBorder {
_ShapedWidgetBorder({
@required this.padding,
side = BorderSide.none,
borderRadius = BorderRadius.zero,
}) : super(side: side, borderRadius: borderRadius);
final double padding;

@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..moveTo(rect.width - 8.0 , rect.top)
..lineTo(rect.width - 20.0, rect.top - 16.0)
..lineTo(rect.width - 32.0, rect.top)
..addRRect(borderRadius
.resolve(textDirection)
.toRRect(Rect.fromLTWH(rect.left, rect.top, rect.width, rect.height - padding)));
}
}

在这种情况下,子小部件位于 appbar 下方

class TestScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> with SingleTickerProviderStateMixin {
AnimationController animationController;
bool _menuShown = false;

@override
void initState() {


animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500));
super.initState();
}

@override
Widget build(BuildContext context) {

Animation opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(animationController);
if (_menuShown)
animationController.forward();
else
animationController.reverse();
return Scaffold(
appBar: AppBar(
elevation: 0.0,
actions: <Widget>[Stack(
overflow: Overflow.visible,
children: <Widget>[IconButton(icon: Icon(Icons.menu), onPressed: (){
setState(() {
_menuShown = !_menuShown;
});
}),
Positioned(
child: FadeTransition(
opacity: opacityAnimation,
child: _ShapedWidget(onlyTop: true,),
),
right: 4.0,
top: 48.0,
),
],)],
),
body: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
child: FadeTransition(
opacity: opacityAnimation,
child: _ShapedWidget(),
),
right: 4.0,
top: -4.0,
),
],
),
);
}
}

class _ShapedWidget extends StatelessWidget {
_ShapedWidget({this.onlyTop = false});
final double padding = 4.0;
final bool onlyTop;

@override
Widget build(BuildContext context) {
return Center(
child: Material(
clipBehavior: Clip.antiAlias,
shape:
_ShapedWidgetBorder(borderRadius: BorderRadius.all(Radius.circular(padding)), padding: padding),
elevation: 4.0,
child: Container(
padding: EdgeInsets.all(padding).copyWith(bottom: padding * 2),
child: onlyTop ? SizedBox(width: 150.0, height: 20.0,) : SizedBox(width: 150.0, height: 250.0, child: Center(child: Text('ShapedWidget'),),),
)),
);
}
}

class _ShapedWidgetBorder extends RoundedRectangleBorder {
_ShapedWidgetBorder({
@required this.padding,
side = BorderSide.none,
borderRadius = BorderRadius.zero,
}) : super(side: side, borderRadius: borderRadius);
final double padding;

@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..moveTo(rect.width - 8.0 , rect.top)
..lineTo(rect.width - 20.0, rect.top - 16.0)
..lineTo(rect.width - 32.0, rect.top)
..addRRect(borderRadius
.resolve(textDirection)
.toRRect(Rect.fromLTWH(rect.left, rect.top, rect.width, rect.height - padding)));
}
}

在这种情况下,子小部件的顶部位于 appbar 上,但 appbar 的高度必须为 0.0

其实我觉得这两种解决方案都不完整,但是可以帮助你找到你需要的东西

关于dart - 如何使用 flutter 创建自定义弹出菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53811115/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com