Flutter中如何禁用整个屏幕的触摸交互?
实现全局屏幕触摸禁用方案
Flutter的AbsorbPointer、IgnorePointer等组件仅能拦截应用内的触摸事件,要实现系统级全局触摸禁用,必须依赖原生平台的API,通过Flutter的MethodChannel调用原生代码完成。以下分平台给出具体实现步骤:
核心思路
Flutter本身无法突破应用沙盒限制直接拦截系统全局触摸,因此需要:
- 在Flutter端通过
MethodChannel与原生层通信 - 原生层根据平台特性,创建全屏拦截触摸的窗口/视图
- 处理平台权限申请(关键,尤其是Android)
Android 实现步骤
1. 申请权限
在android/app/src/main/AndroidManifest.xml中添加悬浮窗权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
2. Flutter端代码
创建工具类封装原生调用:
import 'package:flutter/services.dart'; import 'dart:io' show Platform; import 'package:url_launcher/url_launcher.dart'; class GlobalTouchController { static const MethodChannel _channel = MethodChannel('global_touch_controller'); /// 检查是否拥有悬浮窗权限(Android) static Future<bool> checkOverlayPermission() async { if (Platform.isAndroid) { return await _channel.invokeMethod<bool>('checkOverlayPermission') ?? false; } return false; } /// 跳转至权限设置页(Android) static Future<void> requestOverlayPermission() async { if (Platform.isAndroid) { await launchUrl(Uri.parse('package:${Platform.packageName}')); } } /// 禁用全局触摸 static Future<void> disableGlobalTouch() async { await _channel.invokeMethod('disableGlobalTouch'); } /// 恢复全局触摸 static Future<void> enableGlobalTouch() async { await _channel.invokeMethod('enableGlobalTouch'); } }
3. Android原生代码(Kotlin)
修改MainActivity.kt,实现MethodChannel的方法处理:
import android.content.Context import android.view.View import android.view.WindowManager import android.provider.Settings import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private lateinit var windowManager: WindowManager private lateinit var touchBlockerView: View private val CHANNEL = "global_touch_controller" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager touchBlockerView = View(this) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "checkOverlayPermission" -> { val hasPermission = Settings.canDrawOverlays(this) result.success(hasPermission) } "disableGlobalTouch" -> { if (!Settings.canDrawOverlays(this)) { result.error("PERMISSION_DENIED", "需要悬浮窗权限", null) return@setMethodCallHandler } val layoutParams = WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY } else { WindowManager.LayoutParams.TYPE_SYSTEM_ALERT }, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, android.graphics.PixelFormat.TRANSLUCENT ) windowManager.addView(touchBlockerView, layoutParams) result.success(null) } "enableGlobalTouch" -> { if (touchBlockerView.parent != null) { windowManager.removeView(touchBlockerView) } result.success(null) } else -> result.notImplemented() } } } }
iOS 实现说明
由于iOS的沙盒限制,普通应用无法直接拦截其他应用的触摸事件,必须通过**辅助功能(Accessibility)**实现,且需要用户手动在「设置-辅助功能」中开启权限:
1. 配置权限描述
在ios/Runner/Info.plist中添加辅助权限说明:
<key>NSAccessibilityUsageDescription</key> <string>需要全局触摸拦截权限以实现屏幕锁定功能</string>
2. 核心实现思路
- 使用
AXObserver监听系统全局触摸事件,在需要禁用时拦截事件传递 - 或创建一个全屏的
UIWindow,设置windowLevel为UIWindowLevelAlert,覆盖整个屏幕并消费所有触摸事件(仅能拦截本应用内触摸,全局拦截需依赖辅助功能)
注意:iOS的全局触摸拦截实现复杂度高,且受系统权限严格限制,建议仅在必要场景使用。
使用示例
在Flutter页面中调用工具类:
ElevatedButton( onPressed: () async { bool hasPermission = await GlobalTouchController.checkOverlayPermission(); if (!hasPermission) { await GlobalTouchController.requestOverlayPermission(); return; } await GlobalTouchController.disableGlobalTouch(); }, child: const Text("禁用全局触摸"), ), ElevatedButton( onPressed: () async { await GlobalTouchController.enableGlobalTouch(); }, child: const Text("恢复全局触摸"), ),
内容的提问来源于stack exchange,提问作者fayzo bngsh
相关产品推荐
相关产品推荐

