At Ensemble, we’re constantly looking for ways to enhance developer experience by making our low-code/no-code framework more intuitive and powerful. Recently, I worked on upgrading our Map Widget to introduce two powerful new features that simplify the location selection and marker interactions:
✅ fixedMarker
: Pins a marker at the map’s center, letting users navigate the map beneath it.
✅ draggableMarker
: Empowers users to drag and reposition markers freely.
These features address critical user needs while boosting flexibility. Let’s dive into why we built them, how they work under the hood, and how you can leverage them in your apps.
🎯 Why We Built These Features
Previously, our Map Widget’s markers were static, forcing users to jump through hoops to adjust locations. Here’s what drove our update:
1️⃣ Simplifying Precise Location Selection
- Problem: Apps like delivery services or property listings require pinpoint accuracy. Moving static markers was cumbersome.
-
Solution:
fixedMarker
keeps the marker centered while users pan the map, making location selection seamless.
2️⃣ Enabling Manual Marker Placement
- Problem: Use cases like marking custom meeting points needed manual drag-and-drop flexibility.
-
Solution:
draggableMarker
lets users reposition markers intuitively with a simple drag.
🚀 Under the Hood: Implementing the Features
📍 fixedMarker
: Always Center Stage
Step 1: Centralizing Marker Data
We created a unified class to manage the marker’s position and icon, ensuring consistency and reducing rendering overhead.
class FixedMarker {
LatLng position;
BitmapDescriptor? icon;
FixedMarker({required this.position, this.icon});
}
// Initialize with a default position
FixedMarker _fixedMarker = FixedMarker(position: widget.controller.defaultCameraLatLng);
Step 2: Optimizing Position Updates
By updating the marker’s position only when it changes (and debouncing map movements), we eliminated flickering and improved performance.
void _onCameraMove(CameraPosition position) {
if (widget.controller.onCameraMove != null) {
_cameraMoveDebouncer.run(() async {
LatLngBounds bounds =
await (await _controller.future).getVisibleRegion();
_executeCameraMoveAction(widget.controller.onCameraMove!, bounds);
});
}
// Only update the position if it's different
if (widget.controller.fixedMarker &&
_fixedMarker.position != position.target) {
setState(() {
_fixedMarker.position = position.target;
});
}
}
🖱️ draggableMarker
: Freedom to Drag and Drop
Enabling Marker Drag
We added a flag to toggle drag functionality and linked it to an event handler that updates the marker’s stored position after movement. The marker’s new position is persisted in real-time, allowing seamless integration with other app components.
markerPayload.marker = Marker(
markerId: markerId,
position: markerPayload.latLng,
icon: markerAsset ?? BitmapDescriptor.defaultMarker,
draggable: widget.controller.draggableMarker, // Enables dragging
consumeTapEvents: true,
onDrag: (latLng) {
_moveCamera(latLng); // Update position on drag
},
onTap: () {
_selectMarker(markerId);
},
);
🛠️ How to Use These Features in Your Ensemble App
Enable fixedMarker
Keep the marker centered while panning by setting fixedMarker: true
in your Map configuration.
Map:
fixedMarker: true
Enable draggableMarker
Allow users to drag markers freely with draggableMarker: true
.
Map:
draggableMarker: true
Combine Both for Ultimate Flexibility
Enable both flags to let users start with a centered marker that becomes draggable on demand.
Map:
fixedMarker: true
draggableMarker: true
🚀 Ready to Try It Yourself?
Explore these features in Ensemble Studio or dive deeper into our documentation:
🔑 Lessons Learned
1️⃣ Debounce Strategically: Throttling camera move events reduced redundant state updates.
2️⃣ Optimize Marker Caching: Centralizing marker data streamlined state management.
3️⃣ Prioritize Developer Control: Clear configuration flags let developers tailor interactions to their app’s needs.
🌟 What’s Next?
We’re just getting started! What features would you like to see in the Map Widget?
- Live location tracking?
- Customizable gesture controls?
Let us know in the comments below! 💬
🚀 Happy building!
Top comments (0)