Skip to content

Jetpack Compose UI Components ​

The :speed-ui module provides drop-in, hardware-accelerated Jetpack Compose widgets designed for automotive dashboards, driver safety HUDs, and telematics settings screens.


🏎️ The SpeedGauge Component ​

SpeedGauge is a circular speedometer gauge rendering custom vector arcs, dynamic speed ticks, smoothed needle motion, and real-time GPS accuracy status.

SpeedGauge Compose Demo
020406080100120140160180 GPS: ±3.4m (Good) 55km/h
Throttle (Live Speed)55 km/h
Min Speed Limit20 km/h
Max Warning Limit80 km/h

📦 Basic Usage ​

kotlin
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.vegsahayyak.speedui.components.SpeedGauge
import com.vegsahayyak.speedui.components.ThemeMode
import com.vegsahayyak.speedcore.units.SpeedUnit

@Composable
fun SpeedometerScreen(
    currentSpeed: Float, 
    warningLimit: Float = 80f,
    minCorridorLimit: Float = 40f
) {
    SpeedGauge(
        speed = currentSpeed,
        warningSpeed = warningLimit,         // Maximum speed ceiling
        minSpeedLimit = minCorridorLimit,    // Minimum highway corridor
        isTrackingActive = true,
        isOverLimit = currentSpeed > warningLimit,
        themeMode = ThemeMode.DARK_GRAY,
        unitLabel = "km/h",
        showGpsAccuracy = true,
        gpsAccuracyMeters = 3.5f,
        onUnitSelected = { selectedIndex ->
            // Handle unit change (e.g. km/h vs mph)
        }
    )
}

⚙️ Component Parameters Reference ​

ParameterTypeDefaultDescription
speedFloatRequiredCurrent instantaneous vehicle speed.
warningSpeedFloatRequiredMaximum speed ceiling threshold.
isTrackingActiveBooleanRequiredWhether GPS tracking is actively running or in standby.
isOverLimitBooleanfalseWhen true, renders red alert glowing tones and warning styles.
modifierModifierModifierModifier to be applied to the gauge container.
minSpeedLimitFloat0fOptional minimum speed corridor limit.
maxSpeedFloat180fMaximum dial scale value (e.g. 180 for km/h, 120 for mph).
unitLabelString"km/h"Text label displayed beneath the digital readout.
unitOptionsList<UiSpeedUnit>UiSpeedUnit.entriesSupported selectable units dropdown options (KMH, MPH, MPS, FPS).
labelStepInt20Numeric interval between major dial tick marks.
onUnitSelected((Int) -> Unit)?nullCallback triggered when the driver taps the unit selector.
themeModeThemeModeThemeMode.SYSTEMColor mode: SYSTEM, DARK_GRAY, OLED_BLACK, HIGH_CONTRAST.
colorSchemeSpeedUiColorScheme?nullOptional custom client branding color scheme.
showGpsAccuracyBooleantrueToggles the real-time GPS accuracy badge on/off.
gpsAccuracyMetersFloat-1fPrecision in meters (≤ 5m Good, ≤ 20m Fair, > 20m Weak).
isHudMirroredBooleanfalseWhen true, flips the gauge vertically for windshield reflection.

🎨 Theme Modes & OLED Optimization ​

The SpeedGauge supports built-in theme presets configured via the ThemeMode enum:

kotlin
enum class ThemeMode {
    SYSTEM,        // Automatically follows Android system Dark/Light mode
    DARK_GRAY,     // Deep charcoal gray background with vibrant accents
    OLED_BLACK,    // Pure true black (#000000) for maximum OLED battery savings
    HIGH_CONTRAST, // Ultra-high visibility yellow/white accents for direct sunlight
    HUD_MIRRORED   // Inverts and mirrors layout vertically for windshield projection
}

🎨 Custom Brand Color Schemes (SpeedUiColorScheme) ​

You can supply fully customized color palettes to SpeedGauge and HudDisplay:

kotlin
val myBrandColors = SpeedUiColorScheme(
    safeColor = Color(0xFF00E676),
    warningApproachColor = Color(0xFFFF9100),
    overSpeedColor = Color(0xFFFF1744),
    underSpeedColor = Color(0xFF00E5FF),
    warningGlowColor = Color(0x88FF1744),
    needleColor = Color(0xFF2979FF)
)

SpeedGauge(
    speed = currentSpeed,
    warningSpeed = 80f,
    isTrackingActive = true,
    colorScheme = myBrandColors
)

🌙 HUD Mode & Windshield Reflection (HudDisplay) ​

The HudDisplay composable offers a dedicated, large-digit (120sp) night-driving display that reflects off a vehicle's windshield. It is strictly rendered against a pure OLED black (#000000) background to minimize battery drain and reduce peripheral glare distractions.

kotlin
import com.vegsahayyak.speedui.components.HudDisplay
import com.vegsahayyak.speedui.components.HudMirrorAxis
import com.vegsahayyak.speedui.components.hudMirror

// Dedicated digital HUD composable
HudDisplay(
    speed = currentSpeed,
    warningSpeed = 80f,
    minSpeedLimit = 40f,
    isTrackingActive = true,
    isMirrored = true,
    unitLabel = "km/h",
    onMirrorToggle = { isMirrored -> /* toggle state */ }
)

// Or mirror any Composable using the hudMirror modifier
Box(modifier = Modifier.hudMirror(isMirrored = true, axis = HudMirrorAxis.VERTICAL)) {
    SpeedGauge(speed = currentSpeed, warningSpeed = 80f, isTrackingActive = true)
}

High Contrast Mode for Daylight Driving ​

When commercial drivers operate in bright, direct sunlight, enable ThemeMode.HIGH_CONTRAST to boost needle visibility:

kotlin
SpeedGauge(
    speed = currentSpeed,
    warningSpeed = 80f,
    isTrackingActive = true,
    themeMode = ThemeMode.HIGH_CONTRAST
)

🧩 Accessibility & Screen Readers ​

SpeedGauge implements Android Accessibility semantics out-of-the-box via SpeedGaugeTokens.contentDescriptionFor(...). Screen readers (TalkBack) will announce contextual updates such as:

"Current speed 78 kilometers per hour, speed limit 80 kilometers per hour. Warning status: normal."


🖼️ XML Layout & ViewBinding Interoperability ​

If your project is built with traditional XML layouts, you can embed SpeedGauge directly using AndroidX ComposeView:

xml
<androidx.compose.ui.platform.ComposeView
    android:id="@+id/speedometerComposeView"
    android:layout_width="match_parent"
    android:layout_height="220dp" />

In your Activity or Fragment:

kotlin
binding.speedometerComposeView.setContent {
    SpeedGauge(
        speed = currentSpeedKmh,
        warningSpeed = 80f,
        minSpeedLimit = 40f,
        isTrackingActive = true,
        isOverLimit = currentSpeedKmh > 80f
    )
}

🪟 The PipWidget Component (:speed-overlay) ​

PipWidget is a floating circular speedometer overlay designed to render over third-party applications (Google Maps, Waze, delivery apps) using SYSTEM_ALERT_WINDOW.

kotlin
import com.vegsahayyak.speedoverlay.PipWidget
import com.vegsahayyak.speedoverlay.PipWidgetConfig

PipWidget(
    speed = currentSpeed,
    unitLabel = "km/h",
    isOverLimit = isOverLimit,
    isUnderLimit = isUnderLimit,
    config = PipWidgetConfig(
        size = 100.dp,
        safeColor = Color(0xFF1FC95E),
        warningColor = Color(0xFFE31D23)
    )
)

PipWidgetConfig Parameters ​

ParameterTypeDefaultDescription
sizeDp100.dpOuter diameter of the circular floating bubble.
safeColorColor0xFF1FC95EOuter border color when driving within normal limits.
warningColorColor0xFFE31D23Outer border color during over-speed violations.
underSpeedColorColor0xFF29B6F6Outer border color during under-speed violations.
backgroundColorColor0x66000000Translucent glassmorphism background color.
speedTextSizeTextUnit36.spDigital speed readout typography size.
unitTextSizeTextUnit14.spSpeed unit label typography size.
textColorColorColor.WhiteText color for speed digits and unit.

🎙️ The VoiceCommandButton Component (:speed-ui) ​

A Floating Action Button (FAB) that captures spoken audio from the driver and triggers speed limit adjustments hands-free.

kotlin
import com.vegsahayyak.speedui.components.VoiceCommandButton
import com.vegsahayyak.speedui.api.VoiceAction

VoiceCommandButton(
    // parser defaults to null (uses built-in internal parser)
    onCommandParsed = { action ->
        when (action) {
            is VoiceAction.SetProfile -> {
                SpeedAssistant.with(context, "YOUR_JWT_LICENSE").setDrivingProfile(action.profile)
            }
            is VoiceAction.ChangeUnit -> {
                println("Switched unit to: ${action.unitName}")
            }
            is VoiceAction.Unknown -> {
                println("Unrecognized voice command")
            }
        }
    }
)

Released under Commercial Enterprise License. Follow us on LinkedIn | Contact Us.