Flutter中PopupMenuButton的自定义形状

如何解决Flutter中PopupMenuButton的自定义形状

我想在Flutter中改变我的PopupMenuButton的形状,想在顶部添加一个三角形,如下图所示,我在谷歌上花了很多时间但没有成就请帮助我我是Flutter的新手所以我不知道如何更改这个认容器,现在它只有白色圆形容器,没有在它上面添加白色箭头/三角形。请帮忙,提前致谢

 popUpMenu= PopupMenuButton<String>(
     key: _menuKey,offset: Offset(50,100),padding: EdgeInsets.all(0.0),onSelected: (value) {
       if (value == "Tax & Additional Charges") {
         endDrawerController.drawerKey.value =
             EndDrawerKeys.TaxAndAdditionalChargesEndDrawer;
         endDrawerController.scaffoldKey.currentState.openEndDrawer();
         print("Entering in tax");
       } else if (value == "Hold this Invoice") {
         endDrawerController.drawerKey.value =
             EndDrawerKeys.HoldInvoiceEndDrawer;
         endDrawerController.scaffoldKey.currentState.openEndDrawer();
       }
     },shape: RoundedRectangleBorder(
         borderRadius: BorderRadius.all(Radius.circular(10.h))),itemBuilder: (context) => [
       PopupMenuItem(
         value: "Tax & Additional Charges",child: popUpMenuSingleItem(
             icon: AppAssets.DeliveryIcon,text: "Tax & Additional Charges",topMargin: 15.h),),PopupMenuItem(
         value: "Hold this Invoice",text: "Hold this Invoice",topMargin: 25.h),],);

这就是我希望我的 PopupMenuButton 出现的方式

enter image description here

解决方法

您可以为自定义 PopupMenuButton 创建形状。

示例...

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,home: HomePage(),);
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          PopupMenuButton(
            offset: Offset(0,50),shape: const TooltipShape(),itemBuilder: (_) => <PopupMenuEntry>[
              PopupMenuItem(
                  child: ListTile(
                leading: const Icon(Icons.calculate_outlined),title: const Text('Tax & Additional Charges'),)),PopupMenuItem(
                  child: ListTile(
                leading: const Icon(Icons.av_timer_outlined),title: const Text('Hold This Invoice'),],),);
  }
}

/// I'm using [RoundedRectangleBorder] as my reference...
class TooltipShape extends ShapeBorder {
  const TooltipShape();

  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();

    path.addRRect(
      _borderRadius.resolve(textDirection).toRRect(rect).deflate(_side.width),);

    return path;
  }

  @override
  Path getOuterPath(Rect rect,{TextDirection? textDirection}) {
    final Path path = Path();
    final RRect rrect = _borderRadius.resolve(textDirection).toRRect(rect);

    path.moveTo(0,10);
    path.quadraticBezierTo(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,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 - 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,);
}
,

试试这个:

class PopMenu extends StatefulWidget {
  @override
  _PopMenuState createState() => _PopMenuState();
}

class _PopMenuState extends State<PopMenu> {
  List<Icon> icons = [
    Icon(Icons.person),Icon(Icons.settings),Icon(Icons.credit_card),];
  GlobalKey _key = LabeledGlobalKey("button_icon");
  OverlayEntry _overlayEntry;
  Offset _buttonPosition;
  bool _isMenuOpen = false;

  void _findButton() {
    RenderBox renderBox = _key.currentContext.findRenderObject();
    _buttonPosition = renderBox.localToGlobal(Offset.zero);
  }

  void _openMenu() {
    _findButton();
    _overlayEntry = _overlayEntryBuilder();
    Overlay.of(context).insert(_overlayEntry);
    _isMenuOpen = !_isMenuOpen;
  }

  void _closeMenu() {
    _overlayEntry.remove();
    _isMenuOpen = !_isMenuOpen;
  }

  OverlayEntry _overlayEntryBuilder() {
    return OverlayEntry(
      builder: (context) {
        return Positioned(
          top: _buttonPosition.dy + 50,left: _buttonPosition.dx - 250,width: 300,child: _popMenu(),);
      },);
  }

  Widget _popMenu() {
    return Column(
      children: [
        Align(
          alignment: Alignment.centerRight,child: Padding(
            padding: EdgeInsets.only(right: 20),child: ClipPath(
              clipper: ArrowClipper(),child: Container(
                width: 17,height: 17,color: Color(0xFFF67C0B9),Container(
          width: 300,height: 300,decoration: BoxDecoration(
            color: Color(0xFFF67C0B9),borderRadius: BorderRadius.circular(4),child: Theme(
            data: ThemeData(
              iconTheme: IconThemeData(
                color: Colors.white,child: Column(
              mainAxisSize: MainAxisSize.min,children: List.generate(
                icons.length,(index) {
                  return GestureDetector(
                    onTap: () {},child: Container(
                      width: 300,height: 100,child: icons[index],);
                },);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          key: _key,decoration: BoxDecoration(
            color: Color(0xFFF5C6373),child: IconButton(
            icon: Icon(Icons.menu),color: Colors.white,onPressed: () {
              _isMenuOpen ? _closeMenu() : _openMenu();
            },);
  }
}

class ArrowClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    path.moveTo(0,size.height);
    path.lineTo(size.width / 2,size.height / 2);
    path.lineTo(size.width,size.height);
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return true;
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?