Scenario Description:

  • A map page is embedded in Flutter and a bottom action bar is superimposed. The map page can be dragged, zoomed and other columns. The column actions of the bottom action bar do not affect the operation of the map page

Simplified repetition:

  • useFlutterThe use ofStackLayout to useUiKitViewNested nativeMKMapViewAnd stack another onebutton(or whateverwidget)

Problem description

  • The first time you drag and scale the native part of the map everything works fine, but click againFlutterPart of thebutton(or whateverwidgetThe native map section loses all responses

UiKitView is a widget that can be embedded into a native iOS View, including click-related gestures, parameter transfer, and parameter encoding. 2, the basic functions needed in the designated viewType, this parameter is a String type, is the View on the iOS type of unique identification, both ends must be consistent, this id need to register to a follow FlutterPlatformViewFactory agreement on the class. 3. In addition, you need a class that complies with the FlutterPlatformView protocol. In this class, you need the native View you need, be it Label, Button, UIScrollView, or MKMapView.

import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) - > Bool {GeneratedPluginRegistrant. Register (with: self) / / withId is flutter viewType parameters, there need to be consistent!!! / / will MapViewFactory registered register this class instance id, MapViewFactory class needs to implement FlutterPlatformViewFactory registrar agreement (forPlugin: "bug.demo.UiKitView")?.register(MapViewFactory(), withId: "bug.demo.MapView") return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } class MapViewFactory: NSObject, FlutterPlatformViewFactory { func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: MapPlatformView(frame, viewId, args)}} class MapPlatformView: NSObject, FlutterPlatformView { var frame: CGRect var viewId: Int64 var args: Any? var mapView: MKMapView // map view init(_ frame: CGRect, _ viewId: Int64, _ args: Any?) { self.frame = frame self.viewId = viewId self.args = args mapView = MKMapView(frame: frame) } func view() -> UIView { mapView } }Copy the code

Simple code restore

The Flutter end:
import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override createState() => _MyApp(); } class _MyApp extends State<MyApp> { @override void initState() { // TODO: implement initState super.initState(); } @override Widget build(BuildContext context) => MaterialApp( title: 'UiKitView Bug', theme: ThemeData( primarySwatch: Colors. Blue, visualDensity: visualDensity adaptivePlatformDensity,), / / home use of stack layout: _byStack (context),); // Widgety_byStack (BuildContext Context) => Scaffold(body: stack (alignment: AlignmentDirectional bottomCenter, children: [UiKitView (/ / viewType is a String viewType: "bug.demo.MapView", ), _buildButton(context), ], ), ); // Widgety_byColumn (BuildContext Context) => Scaffold(body: column (children: [Expanded(child: UiKitView( viewType: "bug.demo.MapView", ), ), _buildButton(context), ], ), ); Widget _buildButton(BuildContext context) => MaterialButton( color: Colors.blue, onPressed: () {}, child: Text(" Click on me for next action!" )); }Copy the code

After testing, the above problems do not occur when using Column layout. Here are the emulator screenshots of Stack and Column layout respectively:


To solve

  • inAppDelegateTo register, add the followingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEndedThis policy means that in nativeViewAfter the party passes through a complete responder chain (i.etouchesEndedAfter method call),FlutterTo prevent nativeViewOn all gesture recognition.
  • There’s another oneFlutterPlatformViewGestureRecognizersBlockingPolicyEagerIt means onlytouchesBeganTo be recognized, and everything elseFlutterStop.
FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
  registrar(forPlugin: "bug.demo.UiKitView")?.register(MapViewFactory(),
                                                             withId: "bug.demo.MapView", gestureRecognizersBlockingPolicy: FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded)
Copy the code