我想创建一个弹出菜单时,从应用程序栏上点击按钮。.我想这样的东西出现:
的数据有没有办法在Flutter中做到这一点?一个包或什么?
qeeaahzv1#
我试过了,但我遇到了一些问题,以这种方式显示子部件。所以,这里有两个解决方案:
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))); } }
字符串在本例中,subwidget位于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的高程实际上,在我看来,这两个解决方案都不完整,但它可以帮助你找到你需要的东西
mepcadol2#
现在回答可能为时已晚。但这可以通过使用OverlayEntry小部件来简单地实现。我们创建一个该形状的小部件,并将其传递给OverlayEntry小部件,然后使用Overlay.of(context).insert(overlayEntry)显示覆盖,并使用overlayEntry.remove方法删除它。下面是创建Custom DropDown Menu的中间链接希望这有帮助!
OverlayEntry
Overlay.of(context).insert(overlayEntry)
overlayEntry.remove
azpvetkf3#
有一个名为flutter_portal的软件包,它的工作方式类似于Overlay/OverlayEntry,但以声明的方式工作。您可以使用它来实现自定义工具提示,上下文菜单或对话框。
kkbh8khc4#
CustomPopupMenu( pressType: PressType.singleClick, controller: menu, arrowColor: AppColor.white, menuBuilder: () => ClipRect( clipBehavior: Clip.hardEdge, child: Container( height: MediaQuery.of(context).size.height * ComponentSize.container1height, width: MediaQuery.of(context).size.width * ComponentSize.conatiner1width, decoration: BoxDecoration( borderRadius: BorderRadius.circular( ComponentSize.borderradius), color: AppColor.white, ), child: ListView.builder( itemCount: Details.length, itemBuilder: (context, index) { return Column( children: [ InkWell( onTap: () { do somthing }, child: Column( children: [ Container( padding: EdgeInsets.only( left: ComponentSize.paddingleft), alignment: Alignment.centerLeft, child: Text( Details[index], style: const TextStyle( color: Colors.black, fontFamily: 'Taml_001'), textAlign: TextAlign.start, ), ), Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only( left: ComponentSize.paddingleft), child: Text(Details[index], style: TextStyle( color: AppColor.black .withOpacity( ComponentSize .opacity1), fontSize: ComponentSize .containerfontsize)), ) ], ), ), const Divider(), ], ); }, ), )), child: Container( color: AppColor.white, padding: EdgeInsets.only( top: ComponentSize.paddingbottom, bottom: ComponentSize.paddingtop, left: ComponentSize.padding1left), width: ComponentSize.container2width, height: ComponentSize.container2height, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: ComponentSize.textcontainerwidth, height: ComponentSize.textcontainerheight, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Text( Tamil, style: const TextStyle( color: Colors.black, fontFamily: 'Taml_001'), ), ), ), SizedBox( width: ComponentSize.textcontainerwidth, height: ComponentSize.textcontainerheight, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Text( English, style: const TextStyle( color: Colors.black), ), ), ) ], ), ), SizedBox( child: Icon( Icons.expand_more, size: ComponentSize.iconarrowsize, color: Colors.black, ), ) ], ), ), ),
字符串
yzxexxkh5#
This is custom Tooltipwidget. You can apply this widget to shape attribute. For example PopupmenuButton(shape: TooltipShapeWidget()); class TooltipShapeWidget extends ShapeBorder { const TooltipShapeWidget(); final BorderSide _side = BorderSide.none; final BorderRadiusGeometry _borderRadius = BorderRadius.zero; @override EdgeInsetsGeometry get dimensions => EdgeInsets.all(_side.width); @override Path getInnerPath( Rect rect, { TextDirection? textDirection, }) { final path = Path(); path.addRRect( _borderRadius.resolve(textDirection).toRRect(rect).deflate(_side.width), ); return path; } @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { final path = Path(); final rrect = _borderRadius.resolve(textDirection).toRRect(rect); path.moveTo(0, 10); path.quadraticBezierTo(0, 0, 10, 0); path.lineTo(rrect.width - 30, 0); path.lineTo(rrect.width - 20, -10); path.lineTo(rrect.width - 10, 0); path.quadraticBezierTo(rrect.width, 0, rrect.width, 10); path.lineTo(rrect.width, rrect.height - 10); path.quadraticBezierTo( rrect.width, rrect.height, rrect.width - 10, rrect.height); path.lineTo(10, rrect.height); path.quadraticBezierTo(0, rrect.height, 0, rrect.height - 10); return path; } @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} @override ShapeBorder scale(double t) => RoundedRectangleBorder( side: _side.scale(t), borderRadius: _borderRadius * t, ); }
5条答案
按热度按时间qeeaahzv1#
我试过了,但我遇到了一些问题,以这种方式显示子部件。所以,这里有两个解决方案:
字符串
在本例中,subwidget位于appbar下方
型
在本例中,子部件的顶部位于appbar上,但appbar必须具有0.0的高程
实际上,在我看来,这两个解决方案都不完整,但它可以帮助你找到你需要的东西
mepcadol2#
现在回答可能为时已晚。但这可以通过使用
OverlayEntry
小部件来简单地实现。我们创建一个该形状的小部件,并将其传递给OverlayEntry
小部件,然后使用Overlay.of(context).insert(overlayEntry)
显示覆盖,并使用overlayEntry.remove
方法删除它。下面是创建Custom DropDown Menu的中间链接
希望这有帮助!
azpvetkf3#
有一个名为flutter_portal的软件包,它的工作方式类似于Overlay/OverlayEntry,但以声明的方式工作。您可以使用它来实现自定义工具提示,上下文菜单或对话框。
kkbh8khc4#
字符串
yzxexxkh5#
字符串