Accessibility Guide
The Lazarillo Maps Flutter plugin is designed to be accessible to all users, including those using screen readers and other assistive technologies. This guide explains the accessibility features available in the plugin and how to customize them.
Overview
The plugin provides accessibility support for all interactive map UI elements:
- Zoom In Button: Increases the map zoom level
- Zoom Out Button: Decreases the map zoom level
- Current Location Button: Centers the map on the user’s current location
- Floor Selector: Allows users to select which building floor to display
- Compass Button: Resets the map bearing to North
All UI elements have proper accessibility attributes that are read by screen readers (TalkBack on Android, VoiceOver on iOS) to describe the purpose of each control.
Configuration
Both iOS and Android support the same accessibility configuration approach through MapAccessibilityConfig. This provides a consistent API across platforms.
All accessibility settings are configured when creating the map using the accessibility parameter in MapConfiguration.
Default Accessibility Texts
By default, the SDK uses the following accessibility descriptions:
| UI Element | Default Text |
|---|---|
| Zoom In Button | ”Zoom in on the map” |
| Zoom Out Button | ”Zoom out on the map” |
| Current Location Button | ”Center map on your current location” |
| Floor Selector | ”Select building floor to display” |
| Compass Button | ”Reset map bearing to North” |
These default texts are provided by the native SDKs and are in English. They follow accessibility best practices by being concise yet descriptive.
Customizing Accessibility
You can customize accessibility settings directly from Flutter code using the MapAccessibilityConfig class. This works on both iOS and Android:
import 'package:lazarillo_maps/lazarillo_maps.dart';
final mapConfig = MapConfiguration(
latitude: 40.7128,
longitude: -74.0060,
zoom: 18,
accessibility: MapAccessibilityConfig(
zoomIn: AccessibilityConfig(
label: 'Acercar mapa',
hint: 'Aumenta el nivel de zoom del mapa',
isAccessible: true,
),
zoomOut: AccessibilityConfig(
label: 'Alejar mapa',
hint: 'Disminuye el nivel de zoom del mapa',
isAccessible: true,
),
userLocation: AccessibilityConfig(
label: 'Mi ubicación',
hint: 'Centra el mapa en tu ubicación actual',
isAccessible: true,
),
floorSelector: AccessibilityConfig(
label: 'Selector de piso',
hint: 'Toca para elegir un piso',
isAccessible: true,
),
compass: AccessibilityConfig(
label: 'Brújula',
hint: 'Restablecer la orientación del mapa al norte',
isAccessible: true,
),
),
);AccessibilityConfig Properties
isAccessible: Whether the element is accessible to screen readers (default:true). Set tofalseto hide from screen readers while keeping it visible and functional.label: The accessibility label that screen readers read when the element is focused. Ifnull, the default label from the native SDK is used.hint: Additional context about what the element does. Ifnull, the default hint from the native SDK is used.
All properties are optional. If not provided, the SDK uses its default values.
Accessibility Best Practices
When customizing accessibility texts, follow these guidelines:
- Be Clear and Concise: Keep descriptions short but informative (ideally under 50 characters)
- Describe the Action: Focus on what the control does, not just what it is
- Use Action Verbs: Start with verbs like “Zoom”, “Center”, “Select”
- Avoid Redundancy: Don’t repeat information that screen readers already announce (like “Button”)
- Match Your App’s Language: Use the same language and tone as the rest of your application
Good Examples
✅ “Increase map zoom level”
✅ “Center map on current location”
✅ “Select floor to display”
✅ “Zoom in on map”
Avoid
❌ “Zoom in button” (redundant - screen reader already says “button”)
❌ “Click here” (not descriptive of the action)
❌ “Zoom” (too vague)
Screen Reader Visibility Control
You can control whether UI elements are accessible to screen readers while keeping them visible and functional. This is useful for:
- Blind users: Hide controls that provide only visual feedback (they can’t see the map changes)
- Low vision users: Keep controls accessible (they can see the visual feedback)
How It Works
When an element is hidden from screen readers:
- ✅ Element remains visible on screen
- ✅ Element remains functional (clickable)
- ❌ Screen readers will skip these elements during navigation
Configuring Screen Reader Visibility
Use the isAccessible property in AccessibilityConfig:
final mapConfig = MapConfiguration(
latitude: 40.7128,
longitude: -74.0060,
zoom: 18,
accessibility: MapAccessibilityConfig(
zoomIn: AccessibilityConfig(
label: 'Acercar mapa',
isAccessible: false, // Hide from screen readers
),
zoomOut: AccessibilityConfig(
label: 'Alejar mapa',
isAccessible: false, // Hide from screen readers
),
userLocation: AccessibilityConfig(
label: 'Mi ubicación',
isAccessible: true, // Keep accessible
),
floorSelector: AccessibilityConfig(
label: 'Selector de piso',
isAccessible: true, // Keep accessible
),
compass: AccessibilityConfig(
label: 'Brújula',
isAccessible: true, // Keep accessible
),
),
);Location Button Click Listener
The current location button provides a callback with detailed information about the operation result, allowing you to display custom messages or handle the result appropriately.
Setting Up the Listener
You can set up a listener to be notified when the user taps the location button on the map:
import 'package:lazarillo_maps/lazarillo_maps.dart';
import 'package:lazarillo_maps/src/lazarillo_maps_platform_interface.dart';
// Set up the listener after the map is ready
await LazarilloMapsPlatform.instance.setOnLocationButtonClickListener(
mapId,
(result) {
if (result.success && result.location != null) {
final location = result.location!;
print('Map centered at: ${location.latitude}, ${location.longitude}');
// Show success message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Map centered at: ${location.latitude.toStringAsFixed(6)}, '
'${location.longitude.toStringAsFixed(6)}',
),
backgroundColor: Colors.green,
),
);
} else {
print('Error: ${result.error}');
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${result.error ?? "Unknown error"}'),
backgroundColor: Colors.red,
),
);
}
},
);Removing the Listener
To remove the listener when it’s no longer needed:
await LazarilloMapsPlatform.instance.removeLocationButtonClickListener(mapId);LocationButtonClickResult
The callback receives a LocationButtonClickResult object with the following properties:
| Property | Type | Description |
|---|---|---|
success | bool | Whether the location was successfully obtained and the map was centered |
location | LzLocation? | The location that was used to center the map (null if operation failed) |
error | String? | Error message if the operation failed (null if operation succeeded) |
Error Scenarios
The callback will be invoked with success = false in the following cases:
- No location available: Location provider couldn’t obtain a valid location within 5 seconds
- No repository: Location repository was not set via
setLocationProvider()(Android only) - Exception occurred: An error occurred while trying to get the location
Compass Button Click Listener
The compass button provides a callback when clicked, which is useful for tracking user interactions or performing additional actions when the user resets the map orientation.
Setting Up the Listener
await LazarilloMapsPlatform.instance.setOnCompassClickListener(
mapId,
(bearing) {
print('Compass clicked! Previous bearing: $bearing');
// The map automatically resets to North (0)
},
);Removing the Listener
await LazarilloMapsPlatform.instance.removeCompassClickListener(mapId);Complete Example
import 'package:flutter/material.dart';
import 'package:lazarillo_maps/lazarillo_maps.dart';
import 'package:lazarillo_maps/src/lazarillo_maps_platform_interface.dart';
class MapExample extends StatefulWidget {
@override
_MapExampleState createState() => _MapExampleState();
}
class _MapExampleState extends State<MapExample> {
String? mapId;
final lazarilloMaps = LazarilloMaps('your-api-key');
@override
void initState() {
super.initState();
_initializeMap();
}
Future<void> _initializeMap() async {
await lazarilloMaps.initialize();
final mapWidget = lazarilloMaps.getLazarilloMapWidget(
MapConfiguration(
latitude: 40.7128,
longitude: -74.0060,
zoom: 15,
),
(id) {
mapId = id;
_setupLocationButtonListener(id);
},
);
}
Future<void> _setupLocationButtonListener(String mapId) async {
await LazarilloMapsPlatform.instance.setOnLocationButtonClickListener(
mapId,
(result) {
if (result.success && result.location != null) {
final location = result.location!;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('📍 Map centered successfully!'),
Text('Lat: ${location.latitude.toStringAsFixed(6)}'),
Text('Lng: ${location.longitude.toStringAsFixed(6)}'),
if (location.floorId != null)
Text('Floor: ${location.floorId}'),
],
),
backgroundColor: Colors.green,
duration: Duration(seconds: 3),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('❌ Error: ${result.error ?? "Unknown error"}'),
backgroundColor: Colors.red,
),
);
}
},
);
}
@override
Widget build(BuildContext context) {
// Return your map widget
return Container();
}
@override
void dispose() {
if (mapId != null) {
LazarilloMapsPlatform.instance.removeLocationButtonClickListener(mapId!);
}
super.dispose();
}
}Testing Accessibility
Testing on iOS
- Enable VoiceOver: Go to Settings > Accessibility > VoiceOver and enable it
- Navigate the Map: Swipe through the map controls and listen to the announcements
- Verify Descriptions: Ensure all controls have meaningful descriptions
- Test Custom Texts: Verify your custom accessibility texts are being used
Testing on Android
- Enable TalkBack: Go to Settings > Accessibility > TalkBack and enable it
- Navigate the Map: Swipe through the map controls and listen to the announcements
- Verify Descriptions: Ensure all controls have meaningful descriptions
- Test Custom Texts: Verify your custom accessibility texts are being used
UI Elements Overview
Zoom Controls
The zoom controls are ImageButton elements positioned on the right side of the map:
- Zoom In: Increases map zoom by 1 level (up to
maxZoom) - Zoom Out: Decreases map zoom by 1 level (down to
minZoom)
Both buttons are visible by default but can be hidden using showZoomIn: false and showZoomOut: false in MapConfiguration.
Current Location Button
The current location button is positioned in the top-right corner of the map. When clicked:
- It centers the map on the user’s current location
- Uses a zoom level of 17.0
- Animates the camera movement smoothly
- Provides a callback with operation result (success/failure and location data)
The button can be hidden using showZoomToLocation: false in MapConfiguration.
Listener Example:
await LazarilloMapsPlatform.instance.setOnLocationButtonClickListener(
mapId,
(result) {
if (result.success && result.location != null) {
// Handle successful location centering
final location = result.location!;
print('Centered at: ${location.latitude}, ${location.longitude}');
} else {
// Handle error case
print('Error: ${result.error}');
}
},
);Floor Selector
The floor selector is a Spinner positioned in the bottom-left corner of the map. It:
- Allows users to select which building floor to display
- Shows only floors available for the current place
- Automatically filters map layers based on the selected floor
The floor selector can be hidden using showFloorSelector: false in MapConfiguration.
Compass Button
The compass button appears in the top-right corner when the map is rotated (bearing is not 0). When clicked:
- It resets the map bearing to 0 (North) with a smooth animation
- It disappears once the map is oriented North
- It provides a callback with the previous bearing
The compass button appearance can be customized using compassIcon in MapConfiguration.
Related Documentation
- Flutter Plugin API Documentation
- Android SDK Accessibility Guide
- Android Accessibility Guidelines
- iOS Accessibility Guidelines
Support
If you encounter accessibility issues or need help customizing accessibility texts, please contact support at lazarillo.app .