Route Style Customization
The SDK supports several visual styles for route lines. Styles are applied independently to the upcoming portion of the route (nextStepsLineStyle) and the portion the user has already traveled (prevStepsLineStyle). This allows you to visually distinguish progress along the route.
Solid Color Route
PlainRouteLine renders a continuous solid line. Set colorHex to any six-digit hex color and lineWith to control the stroke width in pixels.
lzMap?.addRoute(
route = route,
nextStepsLineStyle = PlainRouteLine(colorHex = "#0066CC", lineWith = 5f),
prevStepsLineStyle = PlainRouteLine(colorHex = "#999999", lineWith = 3f)
) { }Dashed Route
DashRouteLine renders a dashed pattern. It accepts the same colorHex and lineWith parameters as PlainRouteLine. Dashed lines are useful for representing completed segments or accessible-route alternatives.
lzMap?.addRoute(
route = route,
nextStepsLineStyle = DashRouteLine(colorHex = "#FF6600", lineWith = 4f),
prevStepsLineStyle = DashRouteLine(colorHex = "#CCCCCC", lineWith = 3f)
) { }Mixed Styles (Upcoming vs Completed)
Mixing style types lets you give the user a clear sense of progress: a solid colored line for the remaining path and a muted dashed line for the path already walked.
lzMap?.addRoute(
route = route,
nextStepsLineStyle = PlainRouteLine(colorHex = "#7000FF", lineWith = 5f), // Solid upcoming
prevStepsLineStyle = DashRouteLine(colorHex = "#AAAAAA", lineWith = 3f) // Dashed completed
) { }Route Animation with animateRoute()
animateRoute plays back the route step by step, advancing the map camera and invoking a callback at each step transition. This is primarily used in preview or demo modes where you want to show the user what the journey will look like before they start walking.
Internally the animation is driven by RouteAnimationController, which pre-computes a plan of AnimationSegment objects (Move, Rotate, FloorTransition, StepBoundary) and replays them through a Handler-based tick loop with time-based interpolation. This ensures smooth, consistent marker movement regardless of device frame-rate variability.
normalSpeed: Walking speed in meters per second used for regular route segments (default 20.0).
largeDistanceSpeed: Optional faster speed applied to segments longer than 150 m. Falls back to normalSpeed when null.
changeFloorTime: The pause duration (in seconds) applied at floor-change steps so the user can register that they are moving between levels (default 2.0).
rotatingIconTime: The time (in seconds) spent rotating the direction indicator at waypoint bends where the heading changes by more than 5 degrees (default 0.0 — disabled).
animationDeltaMs: The tick interval in milliseconds for the animation loop (default 50). Lower values produce smoother marker movement at the cost of more frequent GeoJSON updates.
frameCamera: When true (default), the camera automatically fits to each floor’s route geometry during floor transitions.
fitPadding: Per-edge padding (in pixels) applied when frameCamera fits the camera to the route. Use RoutePadding.dp(context, ...) for density-independent values. Default: RoutePadding() (120 px on each side).
lzMap?.animateRoute(
route = route,
aheadStyle = PlainRouteLine(colorHex = "#D2E0EB", lineWith = 4f),
behindStyle = PlainRouteLine(colorHex = "#7000FF", lineWith = 4f),
normalSpeed = 20.0,
largeDistanceSpeed = 40.0,
changeFloorTime = 2.0,
rotatingIconTime = 0.5,
animationDeltaMs = 50,
frameCamera = true,
fitPadding = RoutePadding.dp(requireContext(), top = 80, bottom = 100)
) { currentStep ->
// Called for each step transition
binding.tvStep.text = currentStep.plainInstructions
}
// Stop animation
lzMap?.stopAnimatedRoute()Animation Segments
The controller breaks each route into a sequence of segments before playback begins:
| Segment | Description |
|---|---|
| Move | Linear interpolation along a polyline sub-segment at the configured speed. |
| Rotate | Pauses movement and smoothly rotates the marker icon between two bearings. |
| FloorTransition | Changes the displayed floor, optionally frames the camera, then pauses for changeFloorTime. |
| StepBoundary | Zero-duration marker that fires the step callback and advances to the next route step. |
This pre-computed plan makes the animation deterministic and testable independently of the map rendering layer.
Manual Step Preview (Next / Previous / Jump)
You can move the route visualization to a specific step without autoplay. This is useful for instruction cards, detail panels, and onboarding previews.
// Jump to step 3 (zero-based index)
lzMap?.goToRouteStep(3)
// Move one step forward / backward
lzMap?.goToNextRouteStep()
lzMap?.goToPreviousRouteStep()
// Read current step index to sync external UI
val currentStep = lzMap?.getCurrentRouteStepIndex()goToRouteStep clamps the requested index to route bounds, pauses active route animation, updates route progress styling, and moves the preview marker to the selected step start.
Pass rotateMap = true to rotate the camera to face the step direction:
lzMap?.goToRouteStep(3, rotateMap = true)
lzMap?.goToNextRouteStep(rotateMap = true)Hide Route Animation Marker
If you only need the route color progress without an overlay icon, hide the animation marker:
// Hide the animation marker (route line still updates)
lzMap?.setRouteAnimationMarkerVisible(false)
// Show it again
lzMap?.setRouteAnimationMarkerVisible(true)Customize Default Route Preview Icon
Use a custom style image id for the route preview/animation marker:
val mapConfig = LazarilloMapConfig().apply {
defaultRouteAnimationIcon = "my_route_icon"
}
// Runtime override (null restores SDK default icon: "route")
lzMap?.setDefaultRouteAnimationIcon("my_route_icon")Related Examples
- Route Calculation and Display - How to calculate and display routes
- Indoor Navigation - Applying styles during live navigation sessions
- Complete Navigation Flow - Full end-to-end navigation example