Quyen Anh Nguyen
Quyen Anh Nguyen

Reputation: 1770

Flutter on tap map marker not working in iOS device

When using flutter_map and flutter_map_marker_cluster to build map with marker I have a problem that sometimes but in quite long duration onTap not working anymore but it only occurred in iOS device. In android and iOS simulator it works normally.

Flutter Map {
   layers: [
        // Layer map cluster marker ---> HERE
        MapCluster.getMapCluster(mapStateNotifier, mapState),
      ],
   children: [
        // map tile layer
        TileLayerWidget(),

        // Location user marker
        CircleLayerWidget(),

        // Compass marker
        MarkerLayerWidget(),
      ],
}
// inside method MapCluster.getMapCluster 
return MarkerClusterLayerOptions(
    // void Function(Marker)?
    onMarkerTap: (Marker marker) {
        // ---> HERE
        // show popup
    }

);

I have tried

  1. Increase size of Marker

  2. Remove other layer, just only marker layer

  3. Search issue in Flutter marker cluster package

I realized that running debug even not jump to break point inside onMarkerTap method when I tap on device. Sometimes it show smoothly, sometimes it so lag even though how many times I touch, it doesn't depend on zoom in/ out, go to background or sync/ async.

Because only iOS device has issue I think 2 packages flutter map & flutter marker cluster conflicts when handling gesture onTap in iOS but I have not find any evidence yet.

Upvotes: 2

Views: 670

Answers (2)

Imit
Imit

Reputation: 98

I had the same issue with an android device. With respect to @Quyen answer, you can easily transfer the compass into an own class and call it in the build method.

Compass:

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_compass/flutter_compass.dart';

class Compass extends StatefulWidget {
  const Compass({Key? key}) : super(key: key);

  @override
  State<Compass> createState() => _CompassState();
}

class _CompassState extends State<Compass> {
  double _heading = 0.0;
  @override
  void initState() {
    super.initState();
    _initCompass();
  }

  void _initCompass() {
    FlutterCompass.events?.listen((CompassEvent event) {
      setState(() {
        _heading = event.heading!;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.topRight,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Transform.rotate(
          angle: (_heading * (pi / 180) * -1),
          child: Transform.rotate(
            angle: 0.75,
            child: //Here comes a Icon or whatever you wanna use
          ),
        ),
      ),
    );
  }
}

Any other class:

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'compass.dart'
class SimpleMap extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          FlutterMap(
            options: MapOptions(
              center: LatLng(51.5, -0.09),
              zoom: 13.0,
            ),
            layers: [
              TileLayerOptions(
                urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                subdomains: ['a', 'b', 'c'],
              ),
            ],
          ),
          Positioned(
            top: 10,
            right: 10,
            child: Compass(),
          ),
        ],
      ),
    );
  }
}

Upvotes: 0

Quyen Anh Nguyen
Quyen Anh Nguyen

Reputation: 1770

Finally, I figured it out. The reason is when using FlutterCompass I called StreamSubscription in init state and it always be called when rotate or shaking phone.

  _compassStream = FlutterCompass.events?.listen((event) {
       // update state with new value event.heading
  });

Solution:

  • Separate state management of compass widget
  • Init the first time, paused and resume appropriately with flag variable.

Upvotes: 1

Related Questions