Skip to content

Instantly share code, notes, and snippets.

@Ahmed-gubara
Last active April 17, 2024 06:25
Show Gist options
  • Save Ahmed-gubara/2d191bcf3e426521f85f5bf44a071cd7 to your computer and use it in GitHub Desktop.
Save Ahmed-gubara/2d191bcf3e426521f85f5bf44a071cd7 to your computer and use it in GitHub Desktop.
use google_maps_flutter on flutter_map > 6.0.0
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart' show MapCamera, PointExtension;
import 'package:google_maps_flutter/google_maps_flutter.dart';
export 'package:google_maps_flutter/google_maps_flutter.dart' show MapType;
const double kGoogleMapMaxZoom = 21.0;
const double kGoogleMapMinZoom = 3.0;
class GoogleMapTileLayer extends StatefulWidget {
final MapType mapType;
final EdgeInsets padding;
final bool trafficEnabled;
final bool buildingsEnabled;
final bool compassEnabled;
final bool myLocationEnabled;
final bool indoorViewEnabled;
final TextDirection? layoutDirection;
const GoogleMapTileLayer({
super.key,
required this.mapType,
this.padding = EdgeInsets.zero,
this.trafficEnabled = false,
this.buildingsEnabled = false,
this.compassEnabled = false,
this.myLocationEnabled = false,
this.indoorViewEnabled = false,
this.layoutDirection,
});
@override
State<GoogleMapTileLayer> createState() => _GoogleMapTileLayerState();
}
class _GoogleMapTileLayerState extends State<GoogleMapTileLayer> {
GoogleMapController? _controller;
// update google map to match the latlng of flutter_map
void mapEvent(MapCamera mapCamera) {
final ctrl = _controller;
if (ctrl != null) {
final center = convertLatLng(mapCamera);
final zoom = mapCamera.zoom;
var rotation = mapCamera.rotation;
final newLatLngZoom = CameraUpdate.newCameraPosition(CameraPosition(target: center, zoom: zoom, bearing: -rotation));
ctrl.moveCamera(newLatLngZoom);
}
}
@override
Widget build(BuildContext context) {
final mapCamera = MapCamera.of(context);
mapEvent(mapCamera);
return Stack(
alignment: Alignment.center,
children: [
IgnorePointer(
child: GoogleMap(
myLocationButtonEnabled: false,
buildingsEnabled: widget.buildingsEnabled,
compassEnabled: widget.compassEnabled,
mapToolbarEnabled: false,
myLocationEnabled: widget.myLocationEnabled,
indoorViewEnabled: widget.indoorViewEnabled,
layoutDirection: widget.layoutDirection,
mapType: widget.mapType,
padding: widget.padding,
rotateGesturesEnabled: false,
scrollGesturesEnabled: false,
tiltGesturesEnabled: false,
trafficEnabled: widget.trafficEnabled,
zoomControlsEnabled: false,
zoomGesturesEnabled: false,
initialCameraPosition: CameraPosition(target: convertLatLng(mapCamera), zoom: mapCamera.zoom),
onMapCreated: (GoogleMapController controller) {
_controller = controller;
WidgetsBinding.instance.addPostFrameCallback((_) {
mapEvent(mapCamera);
setState(() {});
});
},
),
),
Container(color: Colors.transparent), // This is important for touch input to work with flutter_map
],
);
}
// steps is used to make map move one pixel at a time by rounding to int, that is to be as close to how flutter_map render its widgets
LatLng convertLatLng(MapCamera mapCamera) {
// latlng
final center = mapCamera.center;
final zoom = mapCamera.zoom;
// adjust map center for padding
final padding = widget.padding;
final top = padding.top;
final right = padding.right;
final bottom = padding.bottom;
final left = padding.left;
final mapCenterPoint = mapCamera.project(center, zoom);
final adjustedCenterPoint = Point(mapCenterPoint.x + left / 2 - right / 2, mapCenterPoint.y + top / 2 - bottom / 2);
final rotatePoint = mapCamera.rotatePoint(mapCenterPoint, adjustedCenterPoint);
final rounded = rotatePoint.round(); // optional
final fixedLatLng = mapCamera.unproject(rounded, zoom);
return LatLng(fixedLatLng.latitude, fixedLatLng.longitude);
}
}
@Ahmed-gubara
Copy link
Author

Ahmed-gubara commented Nov 3, 2023

For previous flutter_map versions before 6.0.0 use this gist
google_tile_layer_widget.dart

usage:

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return FlutterMap(
      options: MapOptions(
        maxZoom: kGoogleMapMaxZoom, // 21.0 : max zoom supported in google_map.
        minZoom: kGoogleMapMinZoom, // 3.0 : any zoom less that 3 will make flutter_map and google_map render incorrectly using different projections.
        initialCenter: LatLng(15.5, 30),
        initialZoom: 5,
      ),
      children: [
        GoogleMapTileLayer(mapType: MapType.normal),
      ],
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment