最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

菜單組件介紹

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

MenuAnchor組件

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

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

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

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

官方示例:

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

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

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

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

MenuItemButton 菜單按鈕組件

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

構(gòu)造方法:

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

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

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

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

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

示例效果:

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

示例源碼:

相較于官方示例,該示例下方展示了上方四個菜單組件的單獨使用以及聯(liá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端例如懸停、點擊、不可點擊等狀態(tài)設(shè)置不同樣式時,會非常的方便。例如系統(tǒng)自帶的顏色、邊框MaterialStateColor、MaterialStateBorderSide等都是通過 MaterialStateProperty擴展的。

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)菜單系列組件

使用平臺原生菜單組件實現(xiàn),非Flutter渲染,例如在MacOS系統(tǒng)上特別有用,因為在MacOS上需要一個系統(tǒng)級菜單。

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

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

小結(jié)

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

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

相關(guān)文章

  • Android NDK開發(fā)(C語言字符串)

    Android NDK開發(fā)(C語言字符串)

    這篇文章主要介紹了Android NDK開發(fā) C語言字符串 ,主要以字符數(shù)組、字符指針及一些字符串常用的方法的方法未來全文展開內(nèi)容,需要的朋友可以參考一下
    2021-12-12
  • Android自定義帶拼音音調(diào)Textview

    Android自定義帶拼音音調(diào)Textview

    這篇文章主要介紹了Android自定義帶拼音音調(diào)的Textview,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Presenting?Streams?in?Flutter小技巧

    Presenting?Streams?in?Flutter小技巧

    這篇文章主要為大家介紹了Presenting?Streams?in?Flutter小技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 解決AMD無法使用Android studio問題

    解決AMD無法使用Android studio問題

    這篇文章主要介紹了AMD無法使用Android studio解決方法,本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • AndroidStudio實現(xiàn)微信界面設(shè)計

    AndroidStudio實現(xiàn)微信界面設(shè)計

    這篇文章帶你通過Androidstudio來實現(xiàn)微信的基礎(chǔ)界面,微信的界面主要包含了主頁、通訊錄、發(fā)現(xiàn)以及我的賬號功能區(qū),下文包含了整個開發(fā)過程,以及解決該問題的過程及思路并提供了源碼
    2021-10-10
  • Android ListView數(shù)據(jù)綁定顯示的三種解決方法

    Android ListView數(shù)據(jù)綁定顯示的三種解決方法

    本篇文章小編為大家介紹,Android ListView數(shù)據(jù)綁定顯示的三種解決方法。需要的朋友參考下
    2013-04-04
  • Android自定義view制作抽獎轉(zhuǎn)盤

    Android自定義view制作抽獎轉(zhuǎn)盤

    這篇文章主要為大家詳細介紹了Android自定義view制作抽獎轉(zhuǎn)盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 一文吃透Android如何處理全局異常

    一文吃透Android如何處理全局異常

    這篇文章主要為大家詳細介紹了Android中處理全局異常的相關(guān)方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • 從源碼分析Android的Volley庫的工作流程

    從源碼分析Android的Volley庫的工作流程

    這篇文章主要介紹了從源碼分析Android的Volley應(yīng)用開發(fā)框架的工作流程,文中對Volley的請求處理和緩存部分介紹得比較詳細,需要的朋友可以參考下
    2016-02-02
  • Android  ListView 條目多樣式展示實例詳解

    Android ListView 條目多樣式展示實例詳解

    這篇文章主要介紹了Android ListView 條目多樣式展示的相關(guān)資料,需要的朋友可以參考下
    2017-04-04

最新評論

东乌珠穆沁旗| 泊头市| 余干县| 广河县| 城固县| 昌宁县| 德钦县| 平乐县| 来安县| 包头市| 宁南县| 固阳县| 信阳市| 托克逊县| 客服| 临邑县| 郎溪县| 临猗县| 东兴市| 花莲县| 石景山区| 澄江县| 灌云县| 五家渠市| 来安县| 吉水县| 玉林市| 海南省| 边坝县| 那曲县| 津南区| 弥勒县| 阿拉善右旗| 东阿县| 肇州县| 伊金霍洛旗| 哈尔滨市| 柳河县| 新竹县| 安塞县| 调兵山市|