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:
- use
Flutter
The use ofStack
Layout to useUiKitView
Nested nativeMKMapView
And 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 again
Flutter
Part of thebutton
(or whateverwidget
The 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
- in
AppDelegate
To register, add the followingPolicy
:FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
This policy means that in nativeView
After the party passes through a complete responder chain (i.etouchesEnded
After method call),Flutter
To prevent nativeView
On all gesture recognition. - There’s another one
FlutterPlatformViewGestureRecognizersBlockingPolicyEager
It means onlytouchesBegan
To be recognized, and everything elseFlutter
Stop.
FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
registrar(forPlugin: "bug.demo.UiKitView")?.register(MapViewFactory(),
withId: "bug.demo.MapView", gestureRecognizersBlockingPolicy: FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded)
Copy the code