Closed arpartydev closed 3 months ago
It may be worth displaying your code where you add the markers to the list. Is this dynamically updated, as I would probably guess the problem is in that code and then not updating properly when the widget has rebuilt
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:schoolmapsg/constants.dart';
import 'package:schoolmapsg/global_variables.dart';
import 'package:schoolmapsg/events/map_events.dart';
import 'package:schoolmapsg/widgets/maps/marker_builder.dart';
class SchoolMap extends StatefulWidget {
const SchoolMap({
super.key,
});
@override
State<SchoolMap> createState() => _SchoolMapState();
}
class _SchoolMapState extends State<SchoolMap> {
static final MapController _mapController = MapController();
static StreamSubscription? subZoomEvent,
subEnableGpsEvent,
subEnabledMyLocationEvent,
subEnabledMyLocationRangeEvent,
subSelectMapEvent;
static double latitude = 1.3521;
static double longitude = 103.8198;
static double zoom = 12.5;
var myLocationMarkers = <Marker>[];
var schoolMarkers = <Marker>[];
var myLocationRangeMarkers = <CircleMarker>[];
subEvents() {
subZoomEvent = eventBus.on<MapControlZoomEvent>().listen((event) {
zoom += event.zoomStep;
_mapController.move(LatLng(latitude, longitude), zoom);
});
subEnableGpsEvent = eventBus.on<EnableGpsEvent>().listen((event) {
displayMyLocRange();
displayMyLoc();
moveTo(myLocation.latitude, myLocation.longitude);
});
subEnabledMyLocationEvent =
eventBus.on<EnableMyLocationEvent>().listen((event) {
if (event.enabled) {
displayMyLocRange();
displayMyLoc();
moveTo(myLocation.latitude, myLocation.longitude);
} else {
myLocationRangeMarkers.clear();
myLocationMarkers.clear();
}
setState(() {});
});
subSelectMapEvent = eventBus.on<SelectMapEvent>().listen((event) {
switch (event.map) {
case SchoolMaps.moekindergarten:
showMoeKindergartenMap();
case SchoolMaps.primaryschool:
showPrimarySchoolMap();
case SchoolMaps.nomap:
clearSchoolMarkers();
}
});
subEnabledMyLocationRangeEvent =
eventBus.on<EnableMyLocationRangeEvent>().listen((event) {
if (event.enabled) {
displayMyLocRange();
} else {
myLocationRangeMarkers.clear();
}
setState(() {});
});
}
@override
void deactivate() {
super.deactivate();
subZoomEvent?.cancel();
subEnableGpsEvent?.cancel();
subEnabledMyLocationEvent?.cancel();
subEnabledMyLocationRangeEvent?.cancel();
subSelectMapEvent?.cancel();
}
@override
void initState() {
super.initState();
subEvents();
myLocationMarkers.clear();
displayMyLocRange();
displayMyLoc();
if (currentMap == SchoolMaps.moekindergarten) {
eventBus.fire(SelectMapEvent(SchoolMaps.moekindergarten));
}
if (currentMap == SchoolMaps.primaryschool) {
eventBus.fire(SelectMapEvent(SchoolMaps.primaryschool));
}
}
void displayMyLoc() {
if (gpsEnabled && displayMyLocation) {
myLocationMarkers.clear();
myLocationMarkers.add(buildMyLocation(
LatLng(myLocation.latitude, myLocation.longitude), context));
}
}
void displayMyLocRange() {
if (gpsEnabled && displayMyLocation && displayMyLocationRange) {
myLocationRangeMarkers.clear();
myLocationRangeMarkers.add(buildMyLocationRange1km(
LatLng(myLocation.latitude, myLocation.longitude), context));
myLocationRangeMarkers.add(buildMyLocationRange2km(
LatLng(myLocation.latitude, myLocation.longitude), context));
}
}
void showMoeKindergartenMap() {
setState(() {
schoolMarkers.clear();
schoolMarkers.addAll(moekindergarten_select_all(context));
});
}
void showPrimarySchoolMap() {
setState(() {
schoolMarkers.clear();
schoolMarkers.addAll(primaryschool_select_all(context));
});
}
void clearSchoolMarkers() {
setState(() {
schoolMarkers.clear();
});
}
void moveTo(double lat, double longi) {
latitude = myLocation.latitude;
longitude = myLocation.longitude;
_mapController.move(LatLng(latitude, longitude), zoom);
}
@override
Widget build(BuildContext context) {
// debugPrint(
// "current location $currentPostion.latitude $currentPostion.longitude");
return FlutterMap(
mapController: _mapController,
options: MapOptions(
initialCenter: LatLng(latitude, longitude),
initialZoom: zoom,
maxZoom: 20.0,
minZoom: 10,
keepAlive: true,
interactionOptions: const InteractionOptions(
enableMultiFingerGestureRace: true,
flags: InteractiveFlag.doubleTapDragZoom |
InteractiveFlag.doubleTapZoom |
InteractiveFlag.drag |
InteractiveFlag.flingAnimation |
InteractiveFlag.pinchZoom |
InteractiveFlag.scrollWheelZoom,
),
onMapEvent: (event) {
if (event is MapEventMove) {
latitude = _mapController.camera.center.latitude;
longitude = _mapController.camera.center.longitude;
// debugPrint(
// "Move ${_mapController.camera.center.latitude} ${_mapController.camera.center.longitude}");
}
if (event is MapEventScrollWheelZoom) {
zoom = _mapController.camera.zoom;
// eventBus.fire(SelectMapEvent(SchoolMaps.primaryschool));
// debugPrint("Zoom ${_mapController.camera.zoom}");
}
}),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
),
CircleLayer(
circles: myLocationRangeMarkers,
),
MarkerLayer(
markers: schoolMarkers,
),
MarkerLayer(
markers: myLocationMarkers,
),
]);
}
}
Code for returning the marker
import 'package:flutter/material.dart';
import 'package:info_popup/info_popup.dart';
import 'package:schoolmapsg/events/map_events.dart';
import 'package:schoolmapsg/global_variables.dart';
import 'package:schoolmapsg/models/primary_school.dart';
class MarkerPrimarySchool extends StatefulWidget {
final PrimarySchool item;
const MarkerPrimarySchool({super.key, required this.item});
@override
State<MarkerPrimarySchool> createState() => _MarkerPrimarySchoolState();
}
class _MarkerPrimarySchoolState extends State<MarkerPrimarySchool> {
bool isSelected = false;
late MaterialColor iconColor;
@override
void initState() {
super.initState();
if (widget.item.nature == "Co-Ed School") {
iconColor = Colors.green;
} else if (widget.item.nature == "Boys School") {
iconColor = Colors.blue;
} else if (widget.item.nature == "Girls School") {
iconColor = Colors.pink;
}
}
@override
Widget build(BuildContext context) {
return InfoPopupWidget(
contentTitle: widget.item.name,
arrowTheme: InfoPopupArrowTheme(
color: Theme.of(context).dividerColor,
arrowDirection: ArrowDirection.down,
),
child: MouseRegion(
onEnter: (event) {},
onExit: (event) {},
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
debugPrint(widget.item.name);
isSelected = true;
setState(() {
eventBus.fire(SelectPrimarySchoolEvent(widget.item, true));
});
},
child: Container(
decoration: BoxDecoration(
// color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(15)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 1,
offset: const Offset(1, 1), // changes position of shadow
),
],
),
child: Icon(
Icons.circle,
size: 15,
color: iconColor,
),
),
),
),
);
}
}
Thanks for the fast reply. I paste the full code here.
showPrimarySchoolMap() will return the marker array which has the repaint issue
lstPrimarySchool will be initialised only once when the app start. Won't be changed after
List<Marker> primaryschool_select_all(context) {
debugPrint("Show Primary School Map");
var schoolMarkers = <Marker>[];
for (int i = 0; i < lstPrimarySchool.length; i++) {
PrimarySchool item = lstPrimarySchool[i];
schoolMarkers.add(Marker(
point:
LatLng(double.parse(item.latitude), double.parse(item.longitude)),
width: 15,
height: 15,
child: MarkerPrimarySchool(
item: item,
)));
}
return schoolMarkers;
}
What happens out of interest if you add a unique Key to your schoolmarkers Marker ?
It works. You're amazing man!
What is the bug?
I am generating some markers on the map. The marker is a simple icon widget. I give the fixed colours to the markers. The marker colour is displayed correctly at the first time.
However when move or zoom the map, the colour of the marker will change randomly.
How can we reproduce it?
Do you have a potential solution?
No response
Platforms
Web Browser
Severity
Minimum: Allows normal functioning