Hi,
I have two map layers: OSM and MapBox Satellite:
layers: [
TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
tileProvider: CachedNetworkTileProvider()
),
TileLayerOptions(
urlTemplate: 'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}@2x.jpg90?access_token={accessToken}',
additionalOptions: {
'accessToken': '...'
},
tileProvider: CachedNetworkTileProvider()
)
]
Is there a way to add a layer switch to switch between both layers?
As workaround I tried to add a button with setState() in onPressed(). However, althought the build() is called, the underlying map is not changing:
_showSatellite = false;
...
layers: [
_showSatellite ? TileLayerOptions(/*mapbox*/) : TileLayerOptions(/*osm*/)
]
...
Button(
onPressed: () {
setState() {
_showSatellite = !_showSatellite;
}
}
)
Any help is appreciated :) Thanks in advance!
Edit: It seems that the layer changes. When I pan or zoom, the switch layer is shown. So, I need a way to refresh the currently shown tiles anyway...
I had the same requirement/issue yesterday and while I know my solution is not optimal in ANY way, it solved the problem for now:
Add the two TileLayerOptions every time but set Opacity: 0 for the one that you don't want to be displayed and Opacity: 1.for the one you want displayed. And call SetState() of course.
(I'm still looking for a way to "force redraw" the entire map at once and not just moving it.)
Looks like something might be coming soon: https://github.com/johnpryan/flutter_map/pull/619
Can't you programmatically include just the required map url and do a move() or whatever into your layers list?
Not quite sure I follow why you need both loaded in a layer, and not just the one that's switched to ?
Not quite sure I follow why you need both loaded in a layer, and not just the one that's switched to ?
I'm my case I need the map layers to update instantly (switching between light/dark mode) without user to having move the map to get the tiles from the selected layer. I will try to use move() in the background to see if that provides the required result.
Phew... there's really no native way to switch map layers without a dirty hack?
The move() will not repaint the current tiles which are cached. Only new tiles come from the switched layer. That seems not to be a good choice:

However, loading two map layers although only one is displayed seems to be a performance and download data issue. I think, I shouldn't do that.
The same thing happens to me, I have not found a solution to the problem.
PR #584 resolves this problem.
You can avoid drop all tiles and reload behavior too see
Looks great! @johnpryan It would be great to get this merged!
I could not fix the error
I use:
flutter_map:
git:
url: git://github.com/johnpryan/flutter_map.git
ref: c590ab12edbf5b6fce30b13a42e974c0abadd506
and
overrideTilesWhenUrlChanges: true,
tileFadeInDuration: 0,
tileFadeInStartWhenOverride: 1.0,
and everything remains the same, Help! Thanks!
@dariomadeira what happens if you use c590ab12edbf5b6fce30b13a42e974c0abadd506 flutter map but you don't provide any settings like this: overrideTilesWhenUrlChanges: true, tileFadeInDuration: 0, tileFadeInStartWhenOverride: 1.0,. By default overrideTilesWhenUrlChanges is false and the map still reloads the tiles but first it drops all old tiles and loads new ones (not overrides them one by one) if it works then tileFadeInStartWhenOverride: true maybe has some bugs.
@maRci002 I don't understand how to fix the error, in my pubspec.yaml I have:
flutter_map:
git:
url: git://github.com/johnpryan/flutter_map.git
ref: c590ab12edbf5b6fce30b13a42e974c0abadd506
and my code is:
import 'package:flutter/material.dart';
import 'package:qrreaderapp/src/models/scan_model.dart';
import 'package:flutter_map/flutter_map.dart';
// import 'package:latlong/latlong.dart';
class MapaPage extends StatefulWidget {
//const MapaPage({Key key}) : super(key: key);
@override
_MapaPageState createState() => _MapaPageState();
}
class _MapaPageState extends State<MapaPage> {
final map = MapController();
String tipoMapa = "streets-v11";
@override
Widget build(BuildContext context) {
final ScanModel scan = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text("Coordenadas QR"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.my_location),
onPressed: (){
map.move(scan.getLatLng(), 15);
},
),
],
),
body: _crearFlutterMap(scan),
floatingActionButton: _crearBotonFlotante(context),
);
}
Widget _crearFlutterMap(ScanModel scan) {
return FlutterMap(
mapController: map,
options: MapOptions(
center: scan.getLatLng(),
zoom: 15,
),
layers: [
_crearMapa(),
_crearMarcadores(scan),
],
);
}
_crearMapa() {
return TileLayerOptions(
urlTemplate : "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}" ,
additionalOptions: {
'accessToken': '<MyToken>',
'id': 'mapbox/$tipoMapa',
}
);
}
_crearMarcadores(ScanModel scan) {
return MarkerLayerOptions(
markers: <Marker> [
Marker(
width: 100.0,
height: 100.0,
point: scan.getLatLng(),
builder: (context) => Container(
child: Icon(Icons.location_on, color: Theme.of(context).primaryColor, size: 70.0),
)
),
]
);
}
Widget _crearBotonFlotante(BuildContext context) {
return FloatingActionButton(
onPressed:(){
setState(() {
if (tipoMapa == "streets-v11") {
tipoMapa = "outdoors-v11";
} else if (tipoMapa == "outdoors-v11") {
tipoMapa = "light-v10";
} else if (tipoMapa == "light-v10") {
tipoMapa = "dark-v10";
} else if (tipoMapa == "dark-v10") {
tipoMapa = "satellite-v9";
} else if (tipoMapa == "satellite-v9") {
tipoMapa = "satellite-streets-v11";
} else {
tipoMapa = "streets-v11";
}
});
},
child: Icon(Icons.repeat),
backgroundColor: Theme.of(context).primaryColor,
);
}
}
the result:
I am new to Flutter, sorry for my English and thank you very much!
@dariomadeira I see the problem now. I haven't checked additionalOptions if it's conetent is changed or not, I'll fix it soon.
Till use this as workaround:
urlTemplate : "https://api.mapbox.com/styles/v1/mapbox/$tipoMapa/tiles/{z}/{x}/{y}?access_token={accessToken}" ,
additionalOptions: {
'accessToken': '<MyToken>',
}
@maRci002
Thank you very much for answering!
@maRci002 Thanks for implementing this. I'm now using 381afd019d34f29e12e997018c65d41e79384964 and it works great to have the map refreshed when changing the map with a different urlTemplate. However, I have a MarkerLayerOptions layer as well where I have an option to show/hide this marker layer. When toggling this marker layer the map layer also gets redrawn even though the urlTemplate has not been changed. Is this by design or am I doing something wrong?
If I use 0.9.0 I can toggle the marker layer without the map being reloaded.
@dariomadeira I see the problem now. I haven't checked
additionalOptionsif it's conetent is changed or not, I'll fix it soon.Till use this as workaround:
urlTemplate : "https://api.mapbox.com/styles/v1/mapbox/$tipoMapa/tiles/{z}/{x}/{y}?access_token={accessToken}" , additionalOptions: { 'accessToken': '<MyToken>', }
Dear @maRci002 I've tried to fix that here #740 . Can you take a look into that MR and give feedback if that's correct?
Most helpful comment
PR #584 resolves this problem.
You can avoid drop all tiles and reload behavior too see