如何通过Java类WindowManager参数实现Flutter Material Button悬浮窗置顶
实现方案(仅Android平台生效)
1 前置权限配置
首先在Android项目的AndroidManifest.xml中添加悬浮窗权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.TYPE_APPLICATION_OVERLAY" />
API 23及以上系统需要动态申请悬浮窗权限,Java代码示例:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); startActivityForResult(intent, 1001); }
2 搭建Flutter与原生通信通道
通过Flutter自带的MethodChannel实现双端指令传递,不需要引入第三方包。
Flutter端示例代码:
import 'package:flutter/services.dart'; // 自定义通道名,避免和其他业务冲突 const platform = MethodChannel('com.example/floating_button'); // 调用原生侧显示悬浮按钮,传入x、y坐标参数 Future<void> showFloatingButton(double x, double y) async { try { await platform.invokeMethod('showButton', {'x': x, 'y': y}); } on PlatformException catch (e) { print("调用失败: ${e.message}"); } } // 调用原生侧更新按钮位置 Future<void> updateButtonPosition(double x, double y) async { try { await platform.invokeMethod('updatePosition', {'x': x, 'y': y}); } on PlatformException catch (e) { print("位置更新失败: ${e.message}"); } }
你可以提前在Flutter路由表中定义单独的悬浮按钮路由,返回你需要的Material Button组件即可。
3 原生Java侧通过WindowManager加载控制组件
在MainActivity中注册MethodChannel的回调,收到Flutter的调用请求后,直接通过WindowManager加载Flutter组件:
private WindowManager windowManager; private View floatingButtonView; private WindowManager.LayoutParams params; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); // 初始化WindowManager布局参数 params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT ); // 注册MethodChannel回调 new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), "com.example/floating_button") .setMethodCallHandler((call, result) -> { if (call.method.equals("showButton")) { // 从Flutter侧获取坐标参数 int x = call.argument("x"); int y = call.argument("y"); params.x = x; params.y = y; // 创建Flutter组件对应的原生View,指定提前定义的悬浮按钮路由 floatingButtonView = Flutter.createView(MainActivity.this, getLifecycle(), "/floatingButton"); windowManager.addView(floatingButtonView, params); result.success(true); } else if (call.method.equals("updatePosition")) { int x = call.argument("x"); int y = call.argument("y"); params.x = x; params.y = y; // 更新悬浮按钮位置 windowManager.updateViewLayout(floatingButtonView, params); result.success(true); } else { result.notImplemented(); } }); }
注意:如果需要处理悬浮按钮的点击事件,直接在Flutter侧定义的Material Button组件内写业务逻辑即可,不需要额外做双端通信。
内容的提问来源于stack exchange,提问作者Mr Dream
相关产品推荐
相关产品推荐

