【问题标题】:How to set Flutter showMenu starting point如何设置 Flutter showMenu 起点
【发布时间】:2020-08-28 13:29:50
【问题描述】:

我想知道如何更改popUpMenu 的原点,在底部应用栏上方启动弹出窗口,无论项目数量如何。与屏幕的右端对齐。类似的东西(例如)

Positioned(right: 0, bottom: bottomAppBarHeight)

下面是我想要实现的popUpMenu的设计布局截图:

这是popUpMenu当前位置的截图(请忽略其他设计差异,因为它们无关紧要):

使用的代码如下:

                      onPressed: () {
                        final RelativeRect position =
                            buttonMenuPosition(context);
                        showMenu(context: context, position: position, items: [
                          PopupMenuItem<int>(
                            value: 0,
                            child: Text('Working a lot harder'),
                          ),
                          PopupMenuItem<int>(
                            value: 1,
                            child: Text('Working a lot less'),
                          ),
                          PopupMenuItem<int>(
                            value: 1,
                            child: Text('Working a lot smarter'),
                          ),
                        ]);
                      },

buttonMenuPosition功能码:

RelativeRect buttonMenuPosition(BuildContext context) {
    final bool isEnglish =
        LocalizedApp.of(context).delegate.currentLocale.languageCode == 'en';
    final RenderBox bar = context.findRenderObject() as RenderBox;
    final RenderBox overlay =
        Overlay.of(context).context.findRenderObject() as RenderBox;
    const Offset offset = Offset.zero;
    final RelativeRect position = RelativeRect.fromRect(
      Rect.fromPoints(
        bar.localToGlobal(
            isEnglish
                ? bar.size.centerRight(offset)
                : bar.size.centerLeft(offset),
            ancestor: overlay),
        bar.localToGlobal(
            isEnglish
                ? bar.size.centerRight(offset)
                : bar.size.centerLeft(offset),
            ancestor: overlay),
      ),
      offset & overlay.size,
    );
    return position;
  }

更改偏移无效。

【问题讨论】:

  • 你能解释一下你想在哪个顺序显示弹出窗口吗?除了你的用户界面上显示的内容。
  • 我想在底部应用栏上方启动弹出窗口,无论项目数量如何。与屏幕的右端对齐。类似于(例如)Positioned(right: 0, bottom: bottomAppBarHeight) 的东西
  • 这不适用于弹出窗口,您必须为其设计自定义小部件
  • 你能给我看一个带代码的例子吗?答案当然不是评论。
  • 所以你想在点击更多选项时打开这个?

标签: flutter flutter-layout


【解决方案1】:

好吧,我无法使用 showMenu 函数实现它,但可以通过使用 PopUpMenuButton 并将其偏移量设置为底部应用栏的高度来实现。

这是一个示例代码:

PopupMenuButton<int>(
    offset: const Offset(0, -380),
    itemBuilder: (context) => [
      PopupMenuItem<int>(
          value: 0,
          child: PopUpMenuTile(
            isActive: true,
            icon: Icons.fiber_manual_record,
            title:'Stop recording',
          )),
      PopupMenuItem<int>(
          value: 1,
          child: PopUpMenuTile(
            isActive: true,
            icon: Icons.pause,
            title: 'Pause recording',
          )),
      PopupMenuItem<int>(
          value: 2,
          child: PopUpMenuTile(
            icon: Icons.group,
            title: 'Members',
          )),
      PopupMenuItem<int>(
          value: 3,
          child: PopUpMenuTile(
            icon: Icons.person_add,
            title: 'Invite members',
          )),
    ],
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Icon(Icons.more_vert,
            color: Colors.white60),
        Text(translate('more'),
            style: Theme.of(context)
                .textTheme
                .caption)
      ],
    ),
  )

自定义弹出菜单图块的代码如下,即使它与问题无关:

class PopUpMenuTile extends StatelessWidget {
  const PopUpMenuTile(
      {Key key,
      @required this.icon,
      @required this.title,
      this.isActive = false})
      : super(key: key);
  final IconData icon;
  final String title;
  final bool isActive;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.start,
      children: <Widget>[
        Icon(icon,
            color: isActive
                ? Theme.of(context).accentColor
                : Theme.of(context).primaryColor),
        const SizedBox(
          width: 8,
        ),
        Text(
          title,
          style: Theme.of(context).textTheme.headline4.copyWith(
              color: isActive
                  ? Theme.of(context).accentColor
                  : Theme.of(context).primaryColor),
        ),
      ],
    );
  }
}

【讨论】:

    【解决方案2】:

    我能够得到类似的行为如下:

        class _SettingsPopupMenuState extends State<SettingsPopupMenu> {
          static const Map<String, IconData> _options = {
           'Settings' : Icons.favorite_border,
           'Share'    : Icons.bookmark_border,
           'Logout'   : Icons.share,
          };
    
          void _showPopup(BuildContext context) async {
            //*get the render box from the context
            final RenderBox renderBox = context.findRenderObject() as RenderBox;
            //*get the global position, from the widget local position
            final offset = renderBox.localToGlobal(Offset.zero);
    
            //*calculate the start point in this case, below the button
            final left = offset.dx;
            final top = offset.dy + renderBox.size.height;
            //*The right does not indicates the width
            final right = left + renderBox.size.width;
    
            //*show the menu
            final value = await showMenu<String>(
              // color: Colors.red,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20.0)
              ),
              context: context, 
              position: RelativeRect.fromLTRB(left, top, right, 0.0), 
              items: _options.entries.map<PopupMenuEntry<String>>((entry) {
                return PopupMenuItem(
                  value: entry.key,
                  child: SizedBox(
                    // width: 200, //*width of popup
                    child: Row(
                      children: [
                        Icon(entry.value, color: Colors.redAccent),
                        const SizedBox(width: 10.0),
                        Text(entry.key)
                      ],
                    ),
                  ),
                );
              }).toList()
            );
    
            print(value);
          }
    
          @override
          Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: const Text('Popup Settings'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  //*encloses the widget from which the relative positions will be 
                  //*taken in a builder, in this case a button
                  Builder(
                    builder: (context) {
                      return RawMaterialButton(
                        fillColor: Colors.indigo,
                        constraints: const BoxConstraints(minWidth: 200),
                        onPressed: () => _showPopup(context),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(8.0)
                        ),
                        padding: const EdgeInsets.symmetric(vertical: 10.0),
                        child: const Text('Show Menu', style: TextStyle(color: 
        Colors.white)),
                      );
                    }
                  ),
                ],
              ),
            ),
          );
        }
      }
    

    【讨论】:

      猜你喜欢
      • 2021-04-07
      • 1970-01-01
      • 2022-01-11
      • 2020-03-16
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-20
      相关资源
      最近更新 更多