Flutter中AndroidViewSurface地图视图pointerIndex异常求助
AndroidViewSurface承载地图视图时拖拽弹窗触发pointerIndex异常
问题描述
使用AndroidViewSurface承载地图视图,当地图上方存在底部弹窗时,拖拽该弹窗过程中若触碰地图视图,会触发PlatformException,报错信息为「invalid pointerIndex」或「pointerIndex out of range」。
开发环境
[!] Flutter (Channel unknown, 3.3.9, on macOS 12.5.1 21G83 darwin-arm, locale ko-KR) ! Flutter version 3.3.9 on channel unknown at /Users/khkong/development/flutter3 ! Upstream repository unknown [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 13.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2022.1) [✓] VS Code (version 1.62.0) [✓] Connected device (3 available) [✓] HTTP Host Availability
AndroidViewSurface相关代码
return PlatformViewLink( viewType: 'plugins.flutter.io/maps', surfaceFactory: (BuildContext context, PlatformViewController controller) { return AndroidViewSurface( controller: controller as AndroidViewController, hitTestBehavior: PlatformViewHitTestBehavior.opaque, gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{} ..add(Factory<PanGestureRecognizer>(() => PanGestureRecognizer())) ..add(Factory<ScaleGestureRecognizer>( () => ScaleGestureRecognizer())) ..add(Factory<TapGestureRecognizer>(() => TapGestureRecognizer())) ..add(Factory<OneSequenceGestureRecognizer>(() => EagerGestureRecognizer())) ..add(Factory<VerticalDragGestureRecognizer>( () => VerticalDragGestureRecognizer())), ); }, onCreatePlatformView: (PlatformViewCreationParams params) { return PlatformViewsService.initSurfaceAndroidView( id: params.id, viewType: 'plugins.flutter.io/edp_maps', layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ) ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..addOnPlatformViewCreatedListener(onPlatformViewCreated) ..create(); }, );
报错日志
错误1
PlatformException(error, invalid pointerIndex 1 for MotionEvent { action=POINTER_UP(1), id[0]=0, x[0]=864.844, y[0]=1468.36, eventTime=32909910000000, downTime=32909877000000, deviceId=4, source=TOUCHSCREEN, displayId=0, eventId=-1041895496}, null, java.lang.IllegalArgumentException: invalid pointerIndex 1 for MotionEvent { action=POINTER_UP(1), id[0]=0, x[0]=864.844, y[0]=1468.36, eventTime=32909910000000, downTime=32909877000000, deviceId=4, source=TOUCHSCREEN, displayId=0, eventId=-1041895496} at android.view.MotionEvent.nativeGetPointerId(Native Method) at android.view.MotionEvent.getPointerId(MotionEvent.java:2842) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3024) at io.flutter.plugin.platform.PlatformViewsController$1.i(SourceFile:12) at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.k(SourceFile:19) at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(SourceFile:7) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.a(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.l(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.m(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.i(Unknown Source:0) at io.flutter.embedding.engine.dart.a.run(Unknown Source:12) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8741) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) ) #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653) #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:296) <asynchronous suspension> #2 AndroidViewController.sendMotionEvent (package:flutter/src/services/platform_views.dart:850) <asynchronous suspension> #3 AndroidViewController.dispatchPointerEvent (package:flutter/src/services/platform_views.dart:950) <asynchronous suspension>
错误2
PlatformException(error, pointerIndex out of range, null, java.lang.IllegalArgumentException: pointerIndex out of range at android.view.MotionEvent.nativeGetPointerId(Native Method) at android.view.MotionEvent.getPointerId(MotionEvent.java:2760) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3631) at io.flutter.plugin.platform.PlatformViewsController$1.i(SourceFile:12) at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.k(SourceFile:19) at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(SourceFile:7) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.a(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.l(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.m(SourceFile:2) at io.flutter.embedding.engine.dart.DartMessenger.i(Unknown Source:0) at io.flutter.embedding.engine.dart.a.run(Unknown Source:12) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8751) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135) ) #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653) #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:296) <asynchronous suspension> #2 AndroidViewController.sendMotionEvent (package:flutter/src/services/platform_views.dart:850) <asynchronous suspension> #3 AndroidViewController.dispatchPointerEvent (package:flutter/src/services/platform_views.dart:950) <asynchronous suspension>
已尝试的解决方案(未生效)
- 在Android原生视图中处理触摸事件监听器
- 为AndroidViewSurface添加gestureRecognizers
解决建议
调整手势识别器优先级与组合
移除EagerGestureRecognizer,它会优先抢占所有手势,可能导致触摸事件分发混乱。同时确保弹窗的手势识别器优先级高于地图的,比如给弹窗的拖拽手势设置更高的识别优先级。修改AndroidViewSurface的hitTestBehavior
将hitTestBehavior改为PlatformViewHitTestBehavior.transparent,让Flutter先处理上层弹窗的触摸事件,再决定是否传递给底层地图视图。拦截触摸事件
在弹窗的父Widget中添加GestureDetector,拦截拖拽过程中的触摸事件,避免事件传递到地图视图:GestureDetector( onVerticalDragUpdate: (details) { // 处理弹窗拖拽逻辑 }, behavior: HitTestBehavior.opaque, child: YourBottomSheetWidget(), )升级Flutter版本
当前使用的Flutter 3.3.9存在已知的PlatformView手势分发bug,升级到3.10及以上版本可修复部分底层触摸事件处理问题。自定义Android视图的触摸事件处理
在Android原生地图视图的Wrapper中,重写dispatchTouchEvent方法,添加指针索引合法性校验,避免抛出异常:@Override public boolean dispatchTouchEvent(MotionEvent event) { try { return super.dispatchTouchEvent(event); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().contains("pointerIndex")) { return false; } throw e; } }
内容的提问来源于stack exchange,提问作者Kyeonghwan.Kong
相关产品推荐
相关产品推荐

