如何在Android14上用C# MVVM MAUI(.NET8)实现悬浮窗应用?
.NET MAUI Android14 全屏+悬浮窗切换实现指引
一、全屏模式实现
MAUI需针对Android平台做专属处理,核心在MainActivity中配置系统UI:
- 打开
Platforms/Android/MainActivity.cs,修改OnCreate方法,通过WindowInsetsController实现Android14适配的全屏:protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // 移除布局限制,隐藏系统状态栏、刘海区域 Window.SetFlags(WindowManagerFlags.LayoutNoLimits, WindowManagerFlags.LayoutNoLimits); Window.InsetsController?.Hide(WindowInsets.Type.SystemBars() | WindowInsets.Type.DisplayCutout()); // 设置点击屏幕时隐藏系统UI(可选) Window.InsetsController?.SystemBarsBehavior = WindowInsetsControllerBehavior.HideWhenTapped; } - 同步在
Platforms/Android/AndroidManifest.xml的theme中添加全屏配置:<style name="Maui.SplashTheme" parent="Theme.Maui.Splash"> <!-- 其他配置 --> <item name="android:windowFullscreen">true</item> </style>
二、悬浮窗模式实现(Android14适配)
Android14对悬浮窗权限管控更严格,按以下步骤推进:
- 权限配置与申请
- 在
AndroidManifest.xml中添加必要权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android13+必需 --> - 运行时引导用户开启悬浮窗权限(该权限无法通过普通动态申请流程):
// 在Android平台代码中调用 if (!Android.Provider.Settings.CanDrawOverlays(this)) { Intent intent = new Intent(Android.Provider.Settings.ActionManageOverlayPermission, Android.Net.Uri.Parse("package:" + PackageName)); StartActivityForResult(intent, 1001); }
- 在
- 创建悬浮窗View
- 使用Application上下文创建悬浮窗,避免依赖Activity生命周期:
var windowManager = GetSystemService(Context.WindowService) as WindowManager; var layoutParams = new WindowManager.LayoutParams { Width = WindowManagerLayoutParams.WrapContent, Height = WindowManagerLayoutParams.WrapContent, Type = WindowManagerLayoutParams.TypeApplicationOverlay, // Android8.0+标准类型 Flags = WindowManagerLayoutParams.FlagNotFocusable | WindowManagerLayoutParams.FlagLayoutInScreen, Format = Android.Graphics.Format.Translucent, Gravity = GravityFlags.Top | GravityFlags.Start }; // 加载自定义悬浮窗布局(可提前在Resources/layout下创建FloatWindow.axml) var floatView = LayoutInflater.From(this).Inflate(Resource.Layout.FloatWindow, null); windowManager.AddView(floatView, layoutParams); - 若要复用MAUI的MVVM页面,可通过
MauiContext将MAUI View转为Android原生View,减少重复代码。
- 使用Application上下文创建悬浮窗,避免依赖Activity生命周期:
三、上滑Home键触发切换逻辑
Android无直接监听上滑Home手势的API,结合HyperOS特性,采用以下方案:
- 监听应用进入后台事件:在MAUI项目中订阅
Application.Current.WillSleep事件,触发悬浮窗显示:Application.Current.WillSleep += (s, e) => { MainThread.BeginInvokeOnMainThread(() => { if (Android.Provider.Settings.CanDrawOverlays(Android.App.Application.Context)) { ShowFloatWindow(); // 调用自定义的悬浮窗显示方法 CurrentActivity?.MoveTaskToBack(true); // 将当前Activity移至后台 } }); }; - 切换双向逻辑:全屏转悬浮窗时隐藏Activity、显示悬浮窗;悬浮窗转全屏时移除悬浮窗、重新唤起Activity并恢复全屏状态。
四、MVVM架构适配
结合你熟悉的MVVM模式,统一状态管理:
- 创建全局
AppStateViewModel,包含IsFullScreen、IsFloatWindowActive两个可绑定属性; - 在Android平台代码中订阅ViewModel的属性变化,自动触发对应UI操作(如设置全屏、显示/隐藏悬浮窗);
- 悬浮窗的交互事件(如点击返回全屏)可通过Command绑定到ViewModel,保持MVVM架构一致性。
五、HyperOS与Android14特殊适配
- 小米HyperOS可能需额外开启应用的「显示在其他应用上层」权限,可在代码中引导用户前往应用设置页开启;
- Android14中
TYPE_APPLICATION_OVERLAY窗口无法覆盖部分系统UI,需调整LayoutParams的Gravity和尺寸适配; - 测试时重点验证悬浮窗在后台的保活逻辑,HyperOS可能对后台窗口有额外管控。
内容的提问来源于stack exchange,提问作者Hưng Nguyễn
相关产品推荐
相关产品推荐

