Flutter_map: Flutter Web - cause layer refresh on resize window?

Created on 16 Apr 2020  路  7Comments  路  Source: fleaflet/flutter_map

image

Tried converting the example to stateful and then calling setState() but that doesn't seem to work
Any thoughts?

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong/latlong.dart';

import 'dart:html';

class LeafletSample extends StatefulWidget {
  static const String route = '/';

  @override
  _LeafletSampleState createState() => _LeafletSampleState();
}

class _LeafletSampleState extends State<LeafletSample> {
  @override
  Widget build(BuildContext context) {

    window.addEventListener("resize", (e) {
      setState(() {});
    });

    var markers = <Marker>[
      Marker(
        width: 80.0,
        height: 80.0,
        point: LatLng(51.5, -0.09),
        builder: (ctx) => Container(
          child: FlutterLogo(
            colors: Colors.blue,
            key: ObjectKey(Colors.blue),
          ),
        ),
      ),
      Marker(
        width: 80.0,
        height: 80.0,
        point: LatLng(53.3498, -6.2603),
        builder: (ctx) => Container(
          child: FlutterLogo(
            colors: Colors.green,
            key: ObjectKey(Colors.green),
          ),
        ),
      ),
      Marker(
        width: 80.0,
        height: 80.0,
        point: LatLng(48.8566, 2.3522),
        builder: (ctx) => Container(
          child: FlutterLogo(
            colors: Colors.purple,
            key: ObjectKey(Colors.purple),
          ),
        ),
      ),
    ];

    return Scaffold(
      appBar: AppBar(title: Text('ExplorerHQ')),
      body: Padding(
        padding: EdgeInsets.all(8.0),
        child: Column(
          children: [
            Padding(
              padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
              child: Text('This is a map that is showing (51.5, -0.9).'),
            ),
            Expanded(
              child: FlutterMap(
                options: MapOptions(
                  center: LatLng(51.5, -0.09),
                  zoom: 2.0,
                  //interactive: false,
                ),
                layers: [
                  TileLayerOptions(
                    urlTemplate:
                        'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                    subdomains: ['a', 'b', 'c'],
                    // For example purposes. It is recommended to use
                    // TileProvider with a caching and retry strategy, like
                    // NetworkTileProvider or CachedNetworkTileProvider
                    tileProvider: NonCachingNetworkTileProvider(),
                    additionalOptions: {'noWrap': 'true'},
                  ),
                  MarkerLayerOptions(markers: markers)
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Most helpful comment

I solve this issue by doing this:

FlutterMap(
   key: Key(MediaQuery.of(context).orientation.toString()),
)

Because its key has also changed, the widget is forced to rebuild when the screen's orientation changes.

The remaining problem is that the position and zoom are also set to default. To solve this, I gave the current position of the map to the new default values when the screen has changed the orientation. Example on the code below:

class MapScreenState extends State<MapScreen>{
  MapController _mapController;

  LatLng _defaultPosition = LatLng(0, 0);

  static const _defaultZoom = 17.0;

  static const _maxZoom = 18.0;

  static const _minZoom = 12.0;

  Orientation screenOrientation;

  bool screenOrientationChanged;

  void initState() {
    _mapController = MapController();
    super.initState();
  }

  Widget build(BuildContext context) {
    screenOrientationChanged = false; 

    if (screenOrientation == null) {
      screenOrientation = MediaQuery.of(context).orientation;
    } else {
      if (screenOrientation != MediaQuery.of(context).orientation) {
        screenOrientationChanged = true;
        screenOrientation = MediaQuery.of(context).orientation;
      }
    }

    return Scaffold(
        body: FlutterMap(
            key: Key(MediaQuery.of(context).orientation.toString()),
            mapController: _mapController,
            options: MapOptions(
                center: screenOrientationChanged ? _mapController.center  : _defaultPosition,
                zoom: screenOrientationChanged ? _mapController.zoom  : _defaultZoom,
                minZoom: _minZoom,
                maxZoom: _maxZoom,
            ),
            layers: [...],
        ),
}

All 7 comments

Same issue on mobile.
I have the map in an Expanded widget as I have a text input below and want to make up for the keyboard opening up. On resize, layers are not re-rendered but just "flip" up.

This happens when changing the orientation of the mobile.

Hey,
same problem here.
For a polygon without HolePointsList everything is fine:
Polygon( points: <LatLng>[ LatLng(52.019799, 8.539140), LatLng(51.736028, 8.769110), LatLng(51.142006, 8.150008), LatLng(51.534121, 7.437587), LatLng(51.998134, 7.615052), ], borderStrokeWidth: 4.0, borderColor: Colors.pink, color: Colors.red.withOpacity(0.5))

When I try to use holePointsList, the layer ignores the borders of the widget
Polygon( points: <LatLng>[ LatLng(52.019799, 8.539140), LatLng(51.736028, 8.769110), LatLng(51.142006, 8.150008), LatLng(51.534121, 7.437587), LatLng(51.998134, 7.615052), ], holePointsList: <List<LatLng>>[ <LatLng>[ LatLng(51.142006, 8.150008), LatLng(51.534121, 7.437587), LatLng(51.998134, 7.615052), ] ], borderStrokeWidth: 4.0, borderColor: Colors.pink, color: Colors.red.withOpacity(0.5))

I actually see this same issue on mobile. Upon rotation, newly revealed tiles do not update, leaving gray blocks. Also, the center point of the map shifts unexpectedly, versus rotating around the center.

I solve this issue by doing this:

FlutterMap(
   key: Key(MediaQuery.of(context).orientation.toString()),
)

Because its key has also changed, the widget is forced to rebuild when the screen's orientation changes.

The remaining problem is that the position and zoom are also set to default. To solve this, I gave the current position of the map to the new default values when the screen has changed the orientation. Example on the code below:

class MapScreenState extends State<MapScreen>{
  MapController _mapController;

  LatLng _defaultPosition = LatLng(0, 0);

  static const _defaultZoom = 17.0;

  static const _maxZoom = 18.0;

  static const _minZoom = 12.0;

  Orientation screenOrientation;

  bool screenOrientationChanged;

  void initState() {
    _mapController = MapController();
    super.initState();
  }

  Widget build(BuildContext context) {
    screenOrientationChanged = false; 

    if (screenOrientation == null) {
      screenOrientation = MediaQuery.of(context).orientation;
    } else {
      if (screenOrientation != MediaQuery.of(context).orientation) {
        screenOrientationChanged = true;
        screenOrientation = MediaQuery.of(context).orientation;
      }
    }

    return Scaffold(
        body: FlutterMap(
            key: Key(MediaQuery.of(context).orientation.toString()),
            mapController: _mapController,
            options: MapOptions(
                center: screenOrientationChanged ? _mapController.center  : _defaultPosition,
                zoom: screenOrientationChanged ? _mapController.zoom  : _defaultZoom,
                minZoom: _minZoom,
                maxZoom: _maxZoom,
            ),
            layers: [...],
        ),
}

I am using mapbox inside animated container and when I change its height, I am having such grayed-out areas on the map. I tried the method above by setting the key of my Mapbox container height (because height changes always)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vinicentus picture vinicentus  路  3Comments

reidterror picture reidterror  路  3Comments

rktvsiim picture rktvsiim  路  5Comments

DanialV picture DanialV  路  6Comments

jacksos101 picture jacksos101  路  3Comments