flutter_map
flutter_map copied to clipboard
[BUG] Exception "`MapCamera` is no longer within the `cameraConstraint` after an option change" when using particular camera setups
What is the bug?
A FlutterMap with a cameraConstraint CameraConstraint.contain(bounds: widget.bounds) gives the assert error "MapCamera is no longer within the cameraConstraint after an option change"
How can we reproduce it?
Put a ValueListenableBuilder and a FlutterMap with a cameraConstraint. Change the ValueListenableBuilder value to trigger a new repaint.
Do you have a potential solution?
I've comment the assert and seems that it works
Platforms
Android
Severity
Erroneous: Prevents normal functioning and causes errors in the console
Hi @dumabg, Can I just double check what version you are running?
It happens the same to me.
pubspect.yaml:
flutter_map: ^6.1.0
flutter_map_cancellable_tile_provider: ^2.0.0
flutter_map_marker_cluster: ^1.3.4
My code:
MapOptions _buildMapOptions() => MapOptions(
initialCenter: widget._parametersMap.currentPosition.center,
initialZoom: widget._parametersMap.initialZoom,
maxZoom: widget._parametersMap.maxZoom,
minZoom: widget._parametersMap.minZoom,
initialRotation: widget._parametersMap.rotation,
cameraConstraint: widget._parametersMap.cameraConstraint,
initialCameraFit: markers.isNotEmpty &&
UserPreferences.getInstance().currentPosition == null
? markers.getCameraFit(
minZoom: widget._parametersMap.minZoom,
maxZoom: widget._parametersMap.initialZoom,
)
: null,
keepAlive: true,
onMapReady: () {
// logger.d('onMapReady !!');
},
onPositionChanged: (MapPosition position, bool hasGesture) {
// logger.d('onPositionChanged hasGesture: $hasGesture,
// position: $position');
if (hasGesture) {
ref.read(mapChangedProvider.notifier).changePosition();
}
},
onTap: (_, __) => widget._popupController.hideAllPopups(),
);
@override
Widget build(BuildContext context) {
final markersAsync = ref.watch(markersProvider);
return markersAsync.when(
data: (values) {
if (values.isNotEmpty) {
setState(() {
markers = List.from(values);
});
}
return PopupScope(
popupController: widget._popupController,
child: Stack(
children: [
FlutterMap(
mapController: widget._mapController,
options: _buildMapOptions(),
children: [
...
],
),
);
},
loading: () => const CustomProgress(),
error: (error, stackTrace) {
context.showSnackbar(
message: error.toString(),
type: MessageType.error,
);
return const SizedBox.shrink();
},
);
}
Error:
MapCamera is no longer within the cameraConstraint after an option change.
'package:flutter_map/src/map/controller/internal.dart':
Failed assertion: line 276 pos 7: 'newOptions.cameraConstraint.constrain(newCamera) == newCamera'
What is the reason for the error?
I can't tell exactly without a more minimal reproducible example, but there's a few things that could be causing issues:
- Building the map options in a function
- Not sure if
initialCameraFit
changes, but changing it will have no effect and could cause issues - Not sure what
PopupScope
is, but maybe that's causing issues?
We need an MRE to investigate this further (standalone, no state from other parts of app, no dependencies, etc.).
@JaffaKetchup @josxha here is a complete single file minimum reproducible example
// ignore_for_file: prefer_const_constructors, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int cnt = 0;
@override
void initState() {
super.initState();
Future(() async {
await Future.delayed(Duration(seconds: 1));
cnt++;
setState(() {});
});
}
@override
Widget build(BuildContext context) {
final camConstraint = cnt > 0
? CameraConstraint.contain(
bounds: LatLngBounds(LatLng(43.6884447292, 20.2201924985),
LatLng(48.2208812526, 29.62654341)))
: null;
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: FlutterMap(
options: MapOptions(
interactionOptions: InteractionOptions(
flags: InteractiveFlag.pinchZoom |
InteractiveFlag.drag |
InteractiveFlag.doubleTapZoom |
InteractiveFlag.scrollWheelZoom,
rotationWinGestures: MultiFingerGesture.none,
rotationThreshold: double.infinity,
cursorKeyboardRotationOptions:
CursorKeyboardRotationOptions.disabled()),
minZoom: 1,
maxZoom: 20,
initialZoom: 5.9,
initialCenter: LatLng(45.80565, 24.937853),
cameraConstraint: camConstraint),
children: []));
}
}
pubspec.yaml
name: flutter_map_constraint_issue
description: "A new Flutter project."
publish_to: "none"
version: 1.0.0+1
environment:
sdk: ">=3.2.5 <4.0.0"
dependencies:
cupertino_icons: ^1.0.2
flutter:
sdk: flutter
flutter_map: ^6.1.0
dev_dependencies:
flutter_lints: ^2.0.0
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
the example above produces after 1 second the error
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building KeyedSubtree-[GlobalKey#de288]:
MapCamera is no longer within the cameraConstraint after an option change.
'package:flutter_map/src/map/controller/internal.dart':
Failed assertion: line 276 pos 7: 'newOptions.cameraConstraint.constrain(newCamera) == newCamera'
The relevant error-causing widget was:
Scaffold Scaffold:file:///D:/temp/flutter_map_constraint_issue/lib/main.dart:56:12
let me know if i can assist or provide anything else.
Thanks @iulian0512, we'll look into this :)
any update on this ? In my case it's not just error in console, but map is not displayed at all (I'm using 6.1.0 as well)
EDIT:
using CameraConstraint.containCenter()
instead of CameraConstraint.contain()
fixed the issue for me (.containerCenter
is slightly different than .contain
, but in my case it doesn't matter)