Skip to content

Version 0.2.1 Alpha

Release Date: July 15, 2024
Status: Alpha Release
Build Number: 0.2.1


Overview

Version 0.2.1 marks a significant milestone in the MINE - Indoor Navigation Engine evolution, introducing a comprehensive UI component system that dramatically improves the developer experience and end-user interface. This release focuses on providing ready-to-use, customizable UI components that integrate seamlessly with your maps.

Alpha Release - Stable

While still in alpha, this release has undergone extensive testing and is significantly more stable than v0.1.0. However, the API may still evolve based on feedback.


Highlights

  • UI Component System


    Complete set of pre-built, customizable UI components for enhanced user experience

  • Theme Support


    Built-in dark/light mode with full customization capabilities

  • 3D/2D Switcher


    Elegant map view switcher with smooth transitions

  • Smart Search


    Advanced search bar with dropdown suggestions


New Features

UI Component Utilities

A powerful new utility system for managing and customizing UI components throughout your navigation interface.

Key Features:

  • ๐ŸŽจ Pre-styled components matching Material Design guidelines
  • ๐Ÿ”ง Easy customization through configuration objects
  • ๐Ÿ“ฑ Responsive layouts that adapt to different screen sizes
  • โ™ฟ Accessibility features built-in
  • ๐ŸŽญ Animation support for smooth transitions

Usage Example:

import com.machinestalk.indoornavigationengine.ui.components.UIComponentManager
import com.machinestalk.indoornavigationengine.ui.components.ComponentConfig

class NavigationActivity : AppCompatActivity() {

    private lateinit var componentManager: UIComponentManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Initialize UI component manager
        componentManager = UIComponentManager(this).apply {
            // Configure component styling
            setComponentConfig(ComponentConfig(
                cornerRadius = 12.dp,
                elevation = 4.dp,
                animationDuration = 300,
                enableHapticFeedback = true
            ))
        }
    }
}
import com.machinestalk.indoornavigationengine.ui.components.UIComponentManager;
import com.machinestalk.indoornavigationengine.ui.components.ComponentConfig;

public class NavigationActivity extends AppCompatActivity {

    private UIComponentManager componentManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initialize UI component manager
        componentManager = new UIComponentManager(this);

        ComponentConfig config = new ComponentConfig.Builder()
            .setCornerRadius(12)
            .setElevation(4)
            .setAnimationDuration(300)
            .setEnableHapticFeedback(true)
            .build();

        componentManager.setComponentConfig(config);
    }
}

3D/2D Map Switcher Button

An elegant, animated button that allows users to seamlessly switch between 3D and 2D map views.

Features:

  • โœจ Smooth transition animations
  • ๐ŸŽฏ Remembers user preference
  • ๐Ÿ“ Adjustable position on screen
  • ๐ŸŽจ Customizable icon and colors
  • ๐Ÿ“ฑ Touch-friendly size (48dp minimum)

Implementation:

import com.machinestalk.indoornavigationengine.ui.components.MapSwitcherButton

// Add switcher button to your layout
val mapSwitcher = MapSwitcherButton(this).apply {
    // Position the button
    setPosition(MapSwitcherButton.Position.TOP_RIGHT)

    // Customize appearance
    setIconTint(Color.WHITE)
    setBackgroundColor(Color.parseColor("#2196F3"))
    setElevation(8.dp)

    // Handle view mode changes
    setOnViewModeChangedListener { mode ->
        when (mode) {
            ViewMode.MODE_3D -> {
                Toast.makeText(context, "Switched to 3D", Toast.LENGTH_SHORT).show()
            }
            ViewMode.MODE_2D -> {
                Toast.makeText(context, "Switched to 2D", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

// Add to scene view
sceneView.addUIComponent(mapSwitcher)
<com.machinestalk.indoornavigationengine.ui.components.MapSwitcherButton
    android:id="@+id/mapSwitcher"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:layout_margin="16dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:iconTint="@color/white"
    app:buttonBackground="@color/primary"
    app:elevation="8dp" />

Visual States:

State Icon Description
3D Mode ๐Ÿ—บ๏ธ Shows 3D perspective view
2D Mode ๐Ÿ—‚๏ธ Shows top-down 2D view
Transitioning โณ Animation in progress

Search Bar with Dropdown

A powerful search interface with intelligent autocomplete and suggestions.

Capabilities:

  • ๐Ÿ” Real-time search suggestions
  • ๐Ÿ“ Search by POI name, category, or location
  • ๐ŸŽฏ Recently searched items
  • ๐Ÿ—‚๏ธ Categorized results
  • โŒจ๏ธ Keyboard navigation support
  • ๐Ÿ“ฑ Voice search integration (optional)

Implementation:

import com.machinestalk.indoornavigationengine.ui.components.SearchBar
import com.machinestalk.indoornavigationengine.ui.components.SearchResult

val searchBar = SearchBar(this).apply {
    // Set hint text
    setHint("Search locations, stores, or services")

    // Enable voice search
    enableVoiceSearch = true

    // Configure search provider
    setSearchProvider { query ->
        // Return search results
        searchPOIs(query)
    }

    // Handle search result selection
    setOnResultSelectedListener { result ->
        // Navigate to selected location
        navigateToLocation(result.location)
    }

    // Configure dropdown appearance
    setDropdownConfig(DropdownConfig(
        maxResults = 10,
        showCategories = true,
        showIcons = true,
        groupByCategory = true
    ))
}

// Add to layout
sceneView.addUIComponent(searchBar)

// Example search function
fun searchPOIs(query: String): List<SearchResult> {
    return poiManager.search(query).map { poi ->
        SearchResult(
            id = poi.id,
            title = poi.name,
            subtitle = poi.category,
            icon = getCategoryIcon(poi.category),
            location = poi.position
        )
    }
}
import com.machinestalk.indoornavigationengine.ui.components.SearchBar;
import com.machinestalk.indoornavigationengine.ui.components.SearchResult;

SearchBar searchBar = new SearchBar(this);
searchBar.setHint("Search locations, stores, or services");
searchBar.setEnableVoiceSearch(true);

// Set search provider
searchBar.setSearchProvider(query -> {
    return searchPOIs(query);
});

// Handle result selection
searchBar.setOnResultSelectedListener(result -> {
    navigateToLocation(result.getLocation());
});

// Add to scene
sceneView.addUIComponent(searchBar);

Search Result Categories:

  • ๐Ÿช Stores & Shops
  • ๐Ÿฝ๏ธ Restaurants & Cafes
  • ๐Ÿšป Facilities & Services
  • ๐Ÿšช Entrances & Exits
  • ๐Ÿ…ฟ๏ธ Parking Areas
  • ๐Ÿšถ Points of Interest

Current Location Button

A prominent button that centers the map on the user's current location.

Features:

  • ๐Ÿ“ Smooth animation to user location
  • ๐Ÿ”„ Auto-refresh location updates
  • ๐ŸŽจ Customizable icon and styling
  • ๐Ÿ’ซ Pulsing animation when active
  • โš ๏ธ Permission handling built-in

Implementation:

import com.machinestalk.indoornavigationengine.ui.components.CurrentLocationButton

val locationButton = CurrentLocationButton(this).apply {
    // Position the button
    setPosition(CurrentLocationButton.Position.BOTTOM_RIGHT)
    setMargin(16.dp)

    // Customize appearance
    setIconTint(Color.WHITE)
    setBackgroundColor(Color.parseColor("#4CAF50"))

    // Enable pulsing animation when tracking
    enablePulseAnimation = true

    // Handle location updates
    setOnLocationUpdateListener { location ->
        // Center map on user location
        sceneView.animateCameraToLocation(
            location = location,
            duration = 500,
            zoom = 18f
        )
    }

    // Handle permission errors
    setOnPermissionDeniedListener {
        showPermissionDialog()
    }
}

sceneView.addUIComponent(locationButton)
@Composable
fun MapWithLocationButton() {
    Box(modifier = Modifier.fillMaxSize()) {
        IndoorNavigationScene(
            mapBuild = mapData,
            modifier = Modifier.fillMaxSize()
        )

        CurrentLocationButton(
            modifier = Modifier
                .align(Alignment.BottomEnd)
                .padding(16.dp),
            onLocationClick = { location ->
                // Handle location click
            }
        )
    }
}

Custom UI Components Support

Build your own UI components that integrate seamlessly with the navigation engine.

Base Classes:

  • BaseUIComponent - Foundation for all UI components
  • OverlayComponent - For floating overlays
  • PanelComponent - For side panels and sheets
  • ButtonComponent - For custom buttons
  • IndicatorComponent - For status indicators

Example Custom Component:

import com.machinestalk.indoornavigationengine.ui.components.BaseUIComponent

class FloorSelectorComponent(context: Context) : BaseUIComponent(context) {

    private val floorButtons = mutableListOf<Button>()

    init {
        setupLayout()
    }

    private fun setupLayout() {
        // Create custom layout
        val layout = LinearLayout(context).apply {
            orientation = LinearLayout.VERTICAL
            setPadding(8.dp, 8.dp, 8.dp, 8.dp)
        }

        // Add floor buttons dynamically
        addView(layout)
    }

    fun setFloors(floors: List<Floor>) {
        floorButtons.clear()
        floors.forEach { floor ->
            val button = Button(context).apply {
                text = floor.name
                setOnClickListener {
                    onFloorSelected(floor)
                }
            }
            floorButtons.add(button)
        }
    }

    override fun onAttached(sceneView: MineSceneView) {
        // Component attached to scene
        super.onAttached(sceneView)
    }

    override fun onDetached() {
        // Clean up
        super.onDetached()
    }
}

Dark/Light Mode Support

Automatic theme switching based on system preferences with full customization options.

Features:

  • ๐ŸŒ“ Automatic system theme detection
  • ๐ŸŽจ Smooth theme transitions
  • ๐Ÿ’พ User preference persistence
  • ๐Ÿ–Œ๏ธ Per-component theme overrides
  • ๐ŸŽญ Custom color schemes

Implementation:

import com.machinestalk.indoornavigationengine.ui.theme.ThemeManager
import com.machinestalk.indoornavigationengine.ui.theme.ThemeMode

// Set up theme manager
val themeManager = ThemeManager(this).apply {
    // Follow system theme (default)
    setThemeMode(ThemeMode.SYSTEM)

    // Or force specific mode
    // setThemeMode(ThemeMode.LIGHT)
    // setThemeMode(ThemeMode.DARK)

    // Listen for theme changes
    setOnThemeChangedListener { mode ->
        when (mode) {
            ThemeMode.LIGHT -> applyLightTheme()
            ThemeMode.DARK -> applyDarkTheme()
        }
    }
}

fun applyLightTheme() {
    sceneView.setThemeConfig(ThemeConfig(
        primaryColor = Color.parseColor("#2196F3"),
        backgroundColor = Color.WHITE,
        textColor = Color.BLACK,
        mapBackgroundColor = Color.parseColor("#F5F5F5")
    ))
}

fun applyDarkTheme() {
    sceneView.setThemeConfig(ThemeConfig(
        primaryColor = Color.parseColor("#1976D2"),
        backgroundColor = Color.parseColor("#121212"),
        textColor = Color.WHITE,
        mapBackgroundColor = Color.parseColor("#1E1E1E")
    ))
}

Color Palettes:

Element Color Usage
Primary #2196F3 Buttons, accents
Background #FFFFFF Main background
Surface #F5F5F5 Cards, panels
Text Primary #212121 Main text
Text Secondary #757575 Subtitles
Element Color Usage
Primary #1976D2 Buttons, accents
Background #121212 Main background
Surface #1E1E1E Cards, panels
Text Primary #FFFFFF Main text
Text Secondary #B0B0B0 Subtitles

Custom Themes

Create fully customized themes that match your brand identity.

Theme Configuration:

import com.machinestalk.indoornavigationengine.ui.theme.CustomTheme

val brandTheme = CustomTheme.Builder()
    // Brand colors
    .setPrimaryColor(Color.parseColor("#FF5722"))
    .setSecondaryColor(Color.parseColor("#FFC107"))
    .setAccentColor(Color.parseColor("#4CAF50"))

    // Background colors
    .setBackgroundColor(Color.WHITE)
    .setSurfaceColor(Color.parseColor("#F5F5F5"))

    // Text colors
    .setTextPrimaryColor(Color.parseColor("#212121"))
    .setTextSecondaryColor(Color.parseColor("#757575"))

    // Component styling
    .setCornerRadius(16.dp)
    .setElevation(8.dp)

    // Map styling
    .setPathColor(Color.parseColor("#4CAF50"))
    .setPathWidth(10f)
    .setPoiMarkerColor(Color.parseColor("#FF5722"))

    // Typography
    .setFontFamily(R.font.custom_font)
    .setTextSizeLarge(20.sp)
    .setTextSizeMedium(16.sp)
    .setTextSizeSmall(14.sp)

    .build()

// Apply custom theme
sceneView.setCustomTheme(brandTheme)

Theme Preview:

// Enable theme preview in debug builds
if (BuildConfig.DEBUG) {
    ThemeManager.showThemePreview(this, brandTheme)
}

Bug Fixes

UI Components Display Issue

Issue: UI components would occasionally disappear or render incorrectly after screen rotation or when returning from background.

Root Cause: Improper lifecycle handling in the component attachment system.

Resolution: - Implemented proper state restoration for all UI components - Added lifecycle-aware component management - Improved view hierarchy management - Enhanced memory handling during configuration changes

Impact: UI components now maintain their state and position reliably across all lifecycle events.

Before:

// Components could lose state on rotation
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // Components would disappear
}

After:

// Components automatically restore state
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // Components maintain state and position
    componentManager.restoreState()
}


3D/2D Map Switcher Button Issues

Issue: The map switcher button had several problems: - Touch events not registering reliably - Animation stuttering during view transitions - Button position incorrect on some screen sizes - State not persisting between sessions

Resolution: - Improved touch target size to meet accessibility standards (48dp minimum) - Optimized animation using hardware acceleration - Implemented responsive positioning system - Added preference persistence using SharedPreferences

Technical Changes:

// Improved touch handling
mapSwitcher.apply {
    minimumWidth = 48.dp
    minimumHeight = 48.dp

    // Hardware accelerated animations
    setLayerType(View.LAYER_TYPE_HARDWARE, null)

    // Smooth transitions
    animate()
        .alpha(1f)
        .setDuration(200)
        .setInterpolator(FastOutSlowInInterpolator())
}

Performance Impact: - Animation frame rate improved from ~45fps to stable 60fps - Touch response time reduced by 40%


Known Issues

Bottom Sheet Layout on Small Screens

Layout Issue

Severity: Medium
Platforms: Small screen devices (< 5.5" diagonal)
Status: Fix planned for v0.3.0

Description: The bottom sheet component may not display optimally on smaller screen devices, with content occasionally extending beyond visible area.

Affected Scenarios: - Search results with many items - POI detail sheets with extensive information - Multi-floor selection panels

Current Workaround:

// Limit content in bottom sheet for small screens
if (isSmallScreen()) {
    bottomSheet.apply {
        maxHeight = screenHeight * 0.6f
        enableScrolling = true
        showExpandButton = true
    }
}

fun isSmallScreen(): Boolean {
    val displayMetrics = resources.displayMetrics
    val screenHeight = displayMetrics.heightPixels / displayMetrics.density
    return screenHeight < 640
}

Status: We're redesigning the bottom sheet layout system to better handle small screens. The fix will include: - Adaptive height calculation - Better scrolling behavior - Collapsible sections for lengthy content


Search Bar Layout Position on Medium Screens

Positioning Issue

Severity: Low
Platforms: Medium screen devices (5.5" - 7" tablets)
Status: Under investigation

Description: On medium-sized screens (particularly small tablets), the search bar may appear slightly offset from the intended position, particularly in landscape orientation.

Impact: - Search bar may overlap with other UI elements - Touch target area may be partially obscured - Visual alignment issues with other components

Temporary Workaround:

// Manual position adjustment for medium screens
searchBar.apply {
    if (isMediumScreen() && isLandscape()) {
        setMargin(
            top = 8.dp,
            start = 16.dp,
            end = 16.dp
        )
    }
}

fun isMediumScreen(): Boolean {
    val screenSize = resources.configuration.screenLayout and 
        Configuration.SCREENLAYOUT_SIZE_MASK
    return screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE
}

Status: Investigating a unified positioning system that works across all screen sizes and orientations.


Upgrade from v0.1.0

Breaking Changes

โš ๏ธ No breaking changes - This release is fully backward compatible with v0.1.0.

Migration Steps

  1. Update Dependency

=== "Gradle (Kotlin)"

   ```kotlin
   dependencies {
       implementation("com.machinestalk:indoornavigationengine:0.2.1-alpha")
   }
   ```

=== "Gradle (Groovy)"

   ```groovy
   dependencies {
       implementation 'com.machinestalk:indoornavigationengine:0.2.1-alpha'
   }
   ```
  1. Sync and Rebuild

    ./gradlew clean build
    

  2. Optional: Add New UI Components

    // Add the new UI components to enhance your app
    sceneView.addUIComponent(MapSwitcherButton(this))
    sceneView.addUIComponent(SearchBar(this))
    sceneView.addUIComponent(CurrentLocationButton(this))
    

While not required, we recommend updating your code to take advantage of new features:

// Before (v0.1.0)
val sceneView = MineSceneView(this)
setContentView(sceneView)

// After (v0.2.1) - with new UI components
val sceneView = MineSceneView(this).apply {
    // Add UI components
    addUIComponent(MapSwitcherButton(context))
    addUIComponent(SearchBar(context))
    addUIComponent(CurrentLocationButton(context))

    // Enable theme support
    ThemeManager(context).setThemeMode(ThemeMode.SYSTEM)
}
setContentView(sceneView)

Testing & Quality

Test Coverage

Feature Coverage Status
UI Components 87% โœ… Pass
Theme System 92% โœ… Pass
Search Functionality 85% โœ… Pass
Map Switcher 90% โœ… Pass
Location Services 78% โš ๏ธ Partial

Device Testing Matrix

Device Category Screen Sizes Android Versions Status
Phones (Small) 4.7" - 5.5" 9 - 14 โš ๏ธ Minor Issues
Phones (Large) 5.5" - 6.7" 9 - 14 โœ… Pass
Tablets (7") 7" - 8" 10 - 14 โš ๏ธ Minor Issues
Tablets (10"+) 10" - 12" 10 - 14 โœ… Pass

Performance Metrics

Metric v0.1.0 v0.2.1 Improvement
Initial Load Time 2.8s 2.1s โฌ‡๏ธ 25%
Memory Usage 145MB 128MB โฌ‡๏ธ 12%
Frame Rate 45fps 58fps โฌ†๏ธ 29%
Component Render 180ms 95ms โฌ‡๏ธ 47%

What's Next - v0.3.0

We're already working on the next release! Here's what's planned:

Confirmed Features

  • ๐Ÿ—บ๏ธ Multi-floor Navigation - Seamless navigation across building levels
  • ๐Ÿ“ POI Categories - Enhanced categorization and filtering
  • ๐ŸŽฏ Route Optimization - Faster path finding algorithms
  • ๐Ÿ”” Notifications - In-app navigation prompts
  • ๐Ÿ“Š Analytics - Usage tracking and insights

Under Consideration

  • ๐ŸŒ Offline Maps - Full offline map support
  • ๐ŸŽค Voice Navigation - Audio turn-by-turn directions
  • โ™ฟ Accessibility Routes - Barrier-free path options
  • ๐ŸŽฎ AR Mode - Augmented reality navigation overlay

Timeline

Expected Release: Q4 2024


Feedback & Support

Your feedback drives our development!


Additional Resources


Contributors

Special thanks to everyone who contributed to this release through testing, feedback, and bug reports!


License

This software is released under the commercial license. Please review the license terms before use.


Thank You for Using MINE!

We appreciate your continued support and feedback. Version 0.2.1 represents a major step forward in making indoor navigation more accessible and user-friendly. Happy coding! ๐ŸŽ‰