欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter3.7新增Menu菜單組件的使用教程分享

 更新時(shí)間:2023年01月31日 15:48:51   作者:老李code  
之前Flutter的菜單選擇、下拉菜單的支持非常簡(jiǎn)單且不友好,對(duì)于非常常見的下拉菜單選擇功能是需要自己自定義實(shí)現(xiàn),今天看到Flutter3.7版本新增了一系列菜單的組件,馬上來試試

菜單組件介紹

本次Flutter穩(wěn)定版本菜單系列組件新增了 MenuAnchorMenuBar、SubmenuButton、MenuItemButton 組件, 這四個(gè)組件可以單獨(dú)使用也可以相互配合使用。他們都位于menu_anchor.dart文件內(nèi),下面對(duì)這幾個(gè)組件詳細(xì)介紹下。

MenuAnchor組件

這是一個(gè)具有子菜單的獨(dú)立區(qū)域組件,點(diǎn)進(jìn)去我們可以看到是一個(gè)StatefulWidget組件, 這四個(gè)組件除了MenuBar是靜態(tài)組件,其他都是動(dòng)態(tài)組件。

說明我們可以當(dāng)作普通的Widget組件去使用它們,MenuAnchor可以獨(dú)立使用,通過這一個(gè)組件可以簡(jiǎn)單的實(shí)現(xiàn)下拉菜單的功能。

構(gòu)造函數(shù):

  const MenuAnchor({
    super.key,
    this.controller,// 控制器
    this.childFocusNode,//如果菜單是輸入框,焦點(diǎn)控制
    this.style, //菜單樣式
    this.alignmentOffset = Offset.zero,//相對(duì)于組件左下角位置
    this.clipBehavior = Clip.none,// 超出屏幕剪切 不常用
    this.anchorTapClosesMenu = false,// 設(shè)置為true時(shí),菜單打開時(shí),點(diǎn)擊會(huì)重復(fù)打開。
    this.onOpen,//打開回調(diào)
    this.onClose,//關(guān)閉回調(diào)
    this.crossAxisUnconstrained = true,
    required this.menuChildren,//下拉菜單列表
    this.builder,//組件本身,通常是控制菜單的按鈕
    this.child,//傳遞給上方builder里的child組件
  });

官方示例:

官方示例菜單后面的字母是自定義快捷鍵的操作,我們重點(diǎn)看下菜單的聯(lián)動(dòng)功能,菜單聯(lián)動(dòng)是和SubmenuButton實(shí)現(xiàn)的,例如官方示例中的設(shè)置背景色的菜單就是使用它實(shí)現(xiàn)的。接下來介紹下這個(gè)組件。

SubmenuButton 聯(lián)級(jí)菜單按鈕

通過這個(gè)按鈕可以實(shí)現(xiàn)菜單的聯(lián)級(jí)調(diào)用,一般用來該選項(xiàng)下還有下級(jí)菜單時(shí)使用。該組件一般和MenuAnchorMenuBar配合使用。

  const SubmenuButton({
    super.key,
    this.onHover,//按鈕是否選中回調(diào) 在pc端屬于鼠標(biāo)指針在此菜單上
    this.onFocusChange,//是否獲取焦點(diǎn)回調(diào)
    this.onOpen,//打開下級(jí)菜單回調(diào)
    this.onClose,//關(guān)閉下級(jí)菜單回調(diào)
    this.style,//按鈕本身樣式
    this.menuStyle,//下級(jí)菜單樣式
    this.alignmentOffset,//相對(duì)位置偏移量 默認(rèn)和組件上邊對(duì)齊
    this.clipBehavior = Clip.none,
    this.focusNode,
    this.statesController,//組件狀態(tài)擴(kuò)展
    this.leadingIcon,//左邊可選圖標(biāo)
    this.trailingIcon,//右邊可選圖標(biāo)
    required this.menuChildren,//聯(lián)級(jí)菜單
    required this.child,//組件本身
  });

MenuItemButton 菜單按鈕組件

具體菜單的選項(xiàng),一般菜單選項(xiàng)沒有下一級(jí)菜單時(shí)具有具體的功能使用,通過構(gòu)造方法可以自定義快捷鍵,快捷鍵功能一般在PC端上使用。

構(gòu)造方法:

  const MenuItemButton({
    super.key,
    this.onPressed,//點(diǎn)擊事件
    this.onHover,//選中回調(diào)
    this.requestFocusOnHover = true,//指針懸停是否聚焦
    this.onFocusChange,//是否獲取焦點(diǎn)回調(diào)
    this.focusNode,//焦點(diǎn)控制
    this.shortcut,//快捷鍵設(shè)置
    this.style,//本身樣式
    this.statesController,//組件狀態(tài)擴(kuò)展
    this.clipBehavior = Clip.none,
    this.leadingIcon,//...
    this.trailingIcon,//...
    required this.child,//...
  });

MenuBar 多菜單聯(lián)級(jí)菜單頭部Bar

此組件是管理多個(gè)聯(lián)級(jí)菜單頭部的組件,例如掘金編輯器下圖,如果菜單選項(xiàng)只有1個(gè)可以使用MenuAnchor,多個(gè)時(shí)使用MenuBar.

紅框內(nèi)的組件集就是MenuBar組件的作用,它可以管理各個(gè)菜單之間的聯(lián)動(dòng),默認(rèn)他們共用一個(gè)控制器。一般和SubmenuButton、MenuItemButton配合使用。

 const MenuBar({
    super.key,
    this.style,// 菜單樣式
    this.clipBehavior = Clip.none,
    this.controller,
    required this.children,
  });

示例效果:

左邊的菜單1、2、3是一組MenuBar組件,右邊是可以獨(dú)立的MenuAnchor組件。

示例源碼:

相較于官方示例,該示例下方展示了上方四個(gè)菜單組件的單獨(dú)使用以及聯(lián)合使用的簡(jiǎn)單示例,去掉了快捷鍵設(shè)置的屬性,更直觀的了解菜單組件的使用。快捷鍵的使用一般在PC端使用。

import 'package:flutter/material.dart';
void main() => runApp(const MenuApp());
enum MenuEntry {
  about('About'),
  showMessage('Show Message'),
  hideMessage('Hide Message'),
  colorMenu('Color Menu'),
  colorRed('Red Background'),
  colorGreen('Green Background'),
  colorBlue('Blue Background');

  final String label;
  const MenuEntry(this.label);
}

class MyCascadingMenu extends StatefulWidget {
  const MyCascadingMenu({super.key, required this.message});

  final String message;

  @override
  State<MyCascadingMenu> createState() => _MyCascadingMenuState();
}

class _MyCascadingMenuState extends State<MyCascadingMenu> {
  MenuEntry? _lastSelection;
  final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Menu Button');

  Color get backgroundColor => _backgroundColor;
  Color _backgroundColor = Colors.red;
  set backgroundColor(Color value) {
    if (_backgroundColor != value) {
      setState(() {
        _backgroundColor = value;
      });
    }
  }

  bool get showingMessage => _showingMessage;
  bool _showingMessage = false;
  set showingMessage(bool value) {
    if (_showingMessage != value) {
      setState(() {
        _showingMessage = value;
      });
    }
  }

  @override
  void dispose() {
    _buttonFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        MenuBar(
            style: MenuStyle(
                backgroundColor:
                    MaterialStateColor.resolveWith((states) => Colors.white),),
            children: [
              SubmenuButton(menuChildren: _meunList(), child: const Text("菜單1")),
              SubmenuButton(menuChildren: _meunList(), child: const Text("菜單2")),
              SubmenuButton(menuChildren: _meunList(), child: const Text("菜單3")),
               MenuAnchor(
          childFocusNode: _buttonFocusNode,
          menuChildren: _meunList(),
          builder:
              (BuildContext context, MenuController controller, Widget? child) {
            return TextButton(
              focusNode: _buttonFocusNode,
              onPressed: () {
                if (controller.isOpen) {
                  controller.close();
                } else {
                  controller.open();
                }
              },
              child: const Text('OPEN MENU'),
            );
          },
        ),
            ]),
       
        Expanded(
          child: Container(
            alignment: Alignment.center,
            color: backgroundColor,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(12.0),
                  child: Text(
                    showingMessage ? widget.message : '',
                    style: Theme.of(context).textTheme.headlineSmall,
                  ),
                ),
                Text(_lastSelection != null
                    ? 'Last Selected: ${_lastSelection!.label}'
                    : ''),
              ],
            ),
          ),
        ),
      ],
    );
  }

  void _activate(MenuEntry selection) {
    setState(() {
      _lastSelection = selection;
    });

    switch (selection) {
      case MenuEntry.about:
        showAboutDialog(
          context: context,
          applicationName: 'MenuBar Sample',
          applicationVersion: '1.0.0',
        );
        break;
      case MenuEntry.hideMessage:
      case MenuEntry.showMessage:
        showingMessage = !showingMessage;
        break;
      case MenuEntry.colorMenu:
        break;
      case MenuEntry.colorRed:
        backgroundColor = Colors.red;
        break;
      case MenuEntry.colorGreen:
        backgroundColor = Colors.green;
        break;
      case MenuEntry.colorBlue:
        backgroundColor = Colors.blue;
        break;
    }
  }

  List<Widget> _meunList() {
    return <Widget>[
      MenuItemButton(
        child: Text(MenuEntry.about.label),
        onPressed: () => _activate(MenuEntry.about),
      ),
      if (_showingMessage)
        MenuItemButton(
          onPressed: () => _activate(MenuEntry.hideMessage),
          child: Text(MenuEntry.hideMessage.label),
        ),
      if (!_showingMessage)
        MenuItemButton(
          onPressed: () => _activate(MenuEntry.showMessage),
          child: Text(MenuEntry.showMessage.label),
        ),
      SubmenuButton(
        leadingIcon: const Icon(Icons.ac_unit_sharp),
        menuChildren: <Widget>[
          MenuItemButton(
            onPressed: () => _activate(MenuEntry.colorRed),
            child: Text(MenuEntry.colorRed.label),
          ),
          MenuItemButton(
            onPressed: () => _activate(MenuEntry.colorGreen),
            child: Text(MenuEntry.colorGreen.label),
          ),
          MenuItemButton(
            onPressed: () => _activate(MenuEntry.colorBlue),
            child: Text(MenuEntry.colorBlue.label),
          ),
        ],
        child: const Text('Background Color'),
      ),
    ];
  }
}

class MenuApp extends StatelessWidget {
  const MenuApp({super.key});

  static const String kMessage = '"Talk less. Smile more." - A. Burr';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(body: MyCascadingMenu(message: kMessage)),
    );
  }
}

菜單樣式 MenuStyle

構(gòu)造方法:

構(gòu)造方法內(nèi)大多數(shù)參數(shù)使用的是 MaterialStateProperty<T>具有狀態(tài)選擇設(shè)置,這樣做的好處是在PC端例如懸停、點(diǎn)擊、不可點(diǎn)擊等狀態(tài)設(shè)置不同樣式時(shí),會(huì)非常的方便。例如系統(tǒng)自帶的顏色、邊框MaterialStateColorMaterialStateBorderSide等都是通過 MaterialStateProperty擴(kuò)展的。

const MenuStyle({
    this.backgroundColor,
    this.shadowColor,
    this.surfaceTintColor,
    this.elevation,
    this.padding,
    this.minimumSize,
    this.fixedSize,
    this.maximumSize,
    this.side,
    this.shape,
    this.mouseCursor,
    this.visualDensity,
    this.alignment,
  });

原生系統(tǒng)菜單系列組件

使用平臺(tái)原生菜單組件實(shí)現(xiàn),非Flutter渲染,例如在MacOS系統(tǒng)上特別有用,因?yàn)樵贛acOS上需要一個(gè)系統(tǒng)級(jí)菜單。

  • PlatformMenuBar
  • PlatformMenu
  • PlatformMenuItem
  • PlatformMenuItemGroup
  • ...

使用方法大同小異,區(qū)別就是這是基于不同平臺(tái)實(shí)現(xiàn)的系統(tǒng)菜單選項(xiàng)。

小結(jié)

上面就是本次更新新增的菜單相關(guān)使用的組件,可以看出這一系列組件更傾向于桌面端使用,里面加入了實(shí)現(xiàn)快捷鍵的操作,反而對(duì)于移動(dòng)端操作需要的菜單以外部分的陰影,菜單彈出動(dòng)畫都沒有找到支持的方法。

以上就是Flutter3.7新增Menu菜單組件的使用教程分享的詳細(xì)內(nèi)容,更多關(guān)于Flutter Menu菜單組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論