flutter 桌面應用之右鍵菜單

?在 Flutter 桌面應用開發中,context_menucontextual_menu 是兩款常用的右鍵菜單插件,各有特色。以下是對它們的對比分析:?


context_menu

  • 集成方式:?通過 ContextMenuArea 組件包裹目標組件,定義菜單項。?掘金

  • 菜單定義:?使用 builder 返回一個 List<Widget>,通常為 ListTile,支持圖標、文字和點擊事件。?掘金

  • 適用場景:?適合需要快速實現簡單右鍵菜單的場景,集成方便,適用于大多數桌面應用。?掘金


contextual_menu

  • 集成方式:?需要手動監聽鼠標右鍵事件,并調用 popUpContextualMenu() 方法顯示菜單。?掘金

  • 菜單定義:?使用 MenuMenuItem 結構,支持普通項、復選框、分隔符和子菜單等多種類型。?掘金

  • 適用場景:?適合需要復雜菜單結構(如多級菜單、復選項)的應用,提供更高的自定義能力。?


總結對比

特性context_menucontextual_menu
集成方式使用組件包裹目標組件,集成簡單手動監聽事件,調用方法顯示菜單,集成復雜
菜單結構簡單,適合基本菜單復雜,支持多級菜單、復選項等
自定義能力限制較多,主要通過 ListTile 實現高度自定義,支持多種菜單項類型
適用場景快速實現基本右鍵菜單實現復雜、結構化的右鍵菜單

建議選擇

  • 選擇 context_menu:?如果你需要快速集成一個簡單的右鍵菜單,且菜單項較為基礎,context_menu 是一個不錯的選擇。?

  • 選擇 contextual_menu:?如果你的應用需要復雜的菜單結構,如多級菜單、復選項等,contextual_menu 提供了更強大的功能和靈活性。

contextmenu

hello word

引入依賴

  contextmenu: ^3.0.0
import 'package:contextmenu/contextmenu.dart';
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: ContextMenuArea(child: Container(color: Colors.grey,padding: EdgeInsets.all(20),child: Text("在這里右鍵"),),builder: (BuildContext context) {return [Container(padding: EdgeInsets.all(10), child: Text('自定義菜單')),ListTile(title: Text("點擊"),onTap: () {ScaffoldMessenger.of(context,).showSnackBar(SnackBar(content: Text("點擊了")));},),];},), // This trailing comma makes auto-formatting nicer for build methods.);}
}

自定義彈出位置

          ///完全自定義位置GestureDetector(onSecondaryTapDown:(details) => showContextMenu(details.globalPosition,context,(BuildContext context) {return [Container(padding: EdgeInsets.all(10),child: Text('自定義菜單'),),ListTile(title: Text("點擊"),onTap: () {ScaffoldMessenger.of(context,).showSnackBar(SnackBar(content: Text("點擊了")));},),];},0.0,200.0,),child: Container(padding: EdgeInsets.all(15),color: Colors.green,child: Text('Tap!'),),),

contextual_menu

hello word

https://pub.dev/packages/contextual_menu

contextual_menu: ^0.1.2
        GestureDetector(onSecondaryTapDown: (details) {Menu menu = Menu(items: [MenuItem(label: 'Copy',onClick: (_) {print('Clicked Copy');},),MenuItem(label: 'Disabled item', disabled: true),MenuItem.checkbox(key: 'checkbox1',label: 'Checkbox1',checked: true,onClick: (menuItem) {print('Clicked Checkbox1');menuItem.checked = !(menuItem.checked == true);},),MenuItem.separator(),],);popUpContextualMenu(menu, placement: Placement.bottomLeft);},child: Container(padding: EdgeInsets.all(15),color: Colors.green,child: Text('Tap!'),),),

popUpContextualMenu

可以看到我們本身沒有傳遞position參數,那么他是怎么感知我鼠標點擊的位置呢

他是通過window記錄的鼠標點擊位置來展示的

NSWindow.mouseLocationOutsideOfEventStream 是 macOS 平臺(AppKit 框架)中的一個屬性,用于獲取當前鼠標在指定窗口中的坐標位置,而不是通過事件觸發獲取的。這個方法非常實用,尤其是在沒有發生鼠標事件時,仍然需要獲取當前鼠標位置的場景下。

var mouseLocationOutsideOfEventStream: NSPoint { get }

  • 返回值:一個 NSPoint,表示鼠標相對于窗口坐標系的位置。

  • 類型:NSWindow 的實例屬性。

自定義ContextMenuArea


在contextmenu中我們看到ContextMenuArea包裝使用非常簡單,我們這里用contextual_menu也包裝一個

import 'dart:ui';import 'package:contextual_menu/contextual_menu.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';typedef ContextMenuBuilder = List<MenuItem> Function(BuildContext context);class ContextualMenuArea extends StatefulWidget {final Widget child;final ContextMenuBuilder builder;const ContextualMenuArea({super.key,required this.child,required this.builder,});@overrideState<StatefulWidget> createState() {return ContextualMenuAreaState();}
}class ContextualMenuAreaState extends State<ContextualMenuArea> {bool _shouldReact = false;Offset? _position;@overrideWidget build(BuildContext context) {return Listener(child: widget.child,onPointerDown: (details) {///kSecondaryMouseButton	0x02	次鍵(一般是右鍵)///PointerDeviceKind.mouse 輸入來源是鼠標_shouldReact =details.kind == PointerDeviceKind.mouse &&details.buttons == kSecondaryMouseButton;},onPointerUp: (details) {if (!_shouldReact) return;_position = details.position;_handleClickPopUp();},);}void _handleClickPopUp() {popUpContextualMenu(Menu(items: widget.builder(context)),position: _position,placement: Placement.bottomRight,);}
}

使用方式

ContextualMenuArea(child: Container(padding: EdgeInsets.all(20),color: Colors.grey,child: Text("ContextualMenuArea"),),builder: (context) {return [MenuItem.submenu(label: "復制",submenu: Menu(items: [MenuItem.checkbox(label: "復制全部", checked: false),MenuItem.checkbox(label: "復制當前", checked: true),],),),MenuItem.separator(),MenuItem(label: "粘貼"),];},)

運行效果

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901367.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901367.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901367.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Tips:用proxy解決前后端分離項目中的跨域問題

在前后端分離項目中&#xff0c;"跨域問題"是瀏覽器基于同源策略&#xff08;Same-Origin Policy&#xff09;對跨域請求的安全限制。當你的前端&#xff08;如運行在 http://localhost:3000 &#xff09;和后端&#xff08;如運行在 http://localhost:8080 &#…

基于 Qt 的圖片處理工具開發(一):拖拽加載與基礎圖像處理功能實現

一、引言 在桌面應用開發中&#xff0c;圖片處理工具的核心挑戰在于用戶交互的流暢性和異常處理的健壯性。本文以 Qt為框架&#xff0c;深度解析如何實現一個支持拖拽加載、亮度調節、角度旋轉的圖片處理工具。通過嚴謹的文件格式校驗、分層的架構設計和用戶友好的交互邏輯&am…

設計模式:依賴倒轉原則 - 依賴抽象,解耦具體實現

一、為什么用依賴倒轉原則&#xff1f; 在軟件開發中&#xff0c;類與類之間的依賴關系是架構設計中的關鍵。如果依賴過于緊密&#xff0c;系統的擴展性和維護性將受到限制。為了應對這一挑戰&#xff0c;依賴倒轉原則&#xff08;Dependency Inversion Principle&#xff0c;…

vue+d3js+fastapi實現天氣柱狀圖折線圖餅圖

說明&#xff1a; vued3jsfastapi實現天氣柱狀圖折線圖餅圖 效果圖&#xff1a; step0:postman 1. 生成天氣數據&#xff08;POST請求&#xff09;&#xff1a;URL: http://localhost:8000/generate-data/?year2024&month3&seed42 方法: POST Headers:Content-Type:…

UE5,LogPackageName黃字警報處理方法

比如這個場景&#xff0c;淘寶搜索&#xff0c;ue5 T臺&#xff0c;轉為ue5.2后&#xff0c;選擇物體&#xff0c;使勁冒錯。 LogPackageName: Warning: DoesPackageExist called on PackageName that will always return false. Reason: 輸入“”為空。 2. 風險很大的刪除法&…

量子代理簽名:量子時代的數字授權革命

1. 量子代理簽名的定義與核心原理 量子代理簽名&#xff08;Quantum Proxy Signature, QPS&#xff09;是經典代理簽名在量子信息領域的延伸&#xff0c;允許原始簽名者&#xff08;Original Signer&#xff09;授權給代理簽名者&#xff08;Proxy Signer&#xff09;代為簽署文…

【ESP32-C6】Base on esptool commands to enable Flash Encryption and Secure Boot

Please refer to Security Guides Security Overview Flash Encryption Secure Boot v2 Security Features Enablement Workflows Vulnerabilities You can base on “esp-idf/examples/security/flash_encryption” example for testing. Partition Table setting&#…

Kotlin 學習-方法和參數類型

/*** kotlin 的方法有三種* */fun main() {/*** 方法一* 1.普通類的成員方法申明與調用* &#xff08;1&#xff09;需要先構建出實例對象&#xff0c;才能訪問成員方法* &#xff08;2&#xff09;實例對象的構建只需要在類名后面加上()* */Person().test()/*** 方法二&#x…

頭歌 | WPS文檔基本操作

若為出現預期結果可私信我答疑 2025年4月9日 第1關&#xff1a;新建WPS文檔和保存文檔 在本地創建一個1.sh,內容寫入echo 我的第一個WPS文檔.docx創建成功點擊工具欄 點擊上傳文件把剛剛創建的1.sh上傳 點擊圖形化 點擊workspace>userfiles, 復制上傳的文件1.sh返回上一級…

使用docker 安裝向量數據庫Milvus

Miluvs 官網 www.milvus.io/ https://milvus.io/docs/zh/install_standalone-docker-compose-gpu.md 一、基本概念 向量數據庫&#xff1a;Milvus是一款云原生向量數據庫&#xff0c;它支持多種類型的向量&#xff0c;如浮點向量、二進制向量等&#xff0c;并且可以處理大規模…

ps 人像學習

視頻&#xff1a; 一ps快捷鍵 1.1 創建圖層 ctrlj 1.2 放大縮小圖片的大小 按住alt 滾輪 1.3 移動圖片 空格 左鍵 1.4 撤回 ctrlz 二 精修的第一步是去除斑點&#xff0c;瑕疵&#xff0c; 2.1 污點修復畫筆工具 新建一個圖層&#xff0c;點擊污點修復工具進行修復…

數據結構第五版【李春葆】

? 數據結構教程上機實驗指導第5版&#xff08;李春葆主編&#xff09;.pdf 數據結構教程&#xff08;第5版&#xff09;&#xff08;李春葆&#xff09;.pdf 數據結構教程&#xff08;第五版&#xff09;課后習題參考答案&#xff08;李春葆&#xff09;.pdf 數據結構教…

(二十三)安卓開發中數據存儲之Room詳解

在安卓開發中&#xff0c;Room 是一個強大的本地數據庫解決方案&#xff0c;它是 Android Jetpack 的一部分&#xff0c;基于 SQLite 構建&#xff0c;提供了更高層次的抽象。Room 簡化了數據庫操作&#xff0c;減少了樣板代碼&#xff0c;同時支持與 LiveData 和 ViewModel 的…

[C++面試] 初始化相關面試點深究

一、入門 1、C中基礎類型的初始化方式有哪些&#xff1f;請舉例說明 ?默認初始化? 對于全局變量和靜態變量&#xff0c;基礎類型&#xff08;如int、float、double等&#xff09;會被初始化為 0&#xff1b;而對于局部變量&#xff0c;其值是未定義的&#xff0c;包含隨機…

網絡安全之-信息收集

域名收集 域名注冊信息 站長之家 https://whois.chinaz.com/ whois 查詢的相關網站有:中國萬網域名WHOIS信息查詢地址: https://whois.aliyun.com/西部數碼域名WHOIS信息查詢地址: https://whois.west.cn/新網域名WHOIS信息查詢地址: http://whois.xinnet.com/domain/whois/in…

Linux網絡http與https

應用層協議HTTP 提示 因為現在大多數都是https&#xff0c;所以就用https來介紹http&#xff0c;https比http多了一個加密功能&#xff0c;不影響介紹http。 什么是http 雖然我們說, 應用層協議是我們程序猿自己定的. 但實際上, 已經有大佬們定義了一些現成的, 又非常好用的…

講解貪心算法

貪心算法是一種常用的算法思想&#xff0c;其在解決問題時每一步都做出在當前狀態下看起來最優的選擇&#xff0c;從而希望最終能夠獲得全局最優解。C作為一種流行的編程語言&#xff0c;可以很好地應用于貪心算法的實現。下面我們來講一篇關于C貪心算法的文章。 目錄 貪心算法…

vue3中watch的使用示例

使用情況說明&#xff1a; 1、父組件中有個表格&#xff0c;點擊表格行的修改基礎信息&#xff0c;彈出修改對話框&#xff1b; 2、修改內容點擊確認&#xff0c;發送請求&#xff0c;后端更新數據&#xff1b;不修改內容不發送請求&#xff1b; 3、可以連續修改&#xff1b…

Spring MVC 請求類型注解詳解

Spring MVC 請求類型注解詳解 1. 核心注解分類 Spring MVC 中的請求處理注解分為以下幾類&#xff1a; 類別注解示例作用范圍方法級注解RequestMapping, GetMapping 等方法級別參數級注解RequestParam, RequestBody方法參數模型/會話注解ModelAttribute, SessionAttributes方…

C#: DxF文件中Spline解析

以下是使用C#解析DXF文件中Spline(樣條曲線)的完整代碼示例&#xff0c;使用流行的netDxf庫來處理DXF文件&#xff1a; 1. 安裝netDxf庫 首先通過NuGet安裝netDxf庫&#xff1a; Install-Package netDxf 2. 完整Spline解析代碼 using System; using System.Collections.Ge…