Skip to content
SuperDragonXD edited this page Apr 2, 2026 · 2 revisions

The user interface (UI) for Lawnicons is built entirely with Jetpack Compose. This modern toolkit allows us to create a declarative and reactive UI, making it more intuitive to build and maintain.

Key characteristics

  • Location: You'll find all UI-related code in the app/src/main/kotlin/app/lawnchair/lawnicons/ui/ directory.
  • Organization:
    • theme/: Contains LawniconsTheme.kt (which sets up Material 3 Expressive, dynamic coloring, and contrast modes) and LawniconsColor.kt (for color palette definitions).
    • components/: This package is for UI building blocks.
      • core/: Generic, reusable Composables like LawniconsScaffold.kt and SimpleListRow.kt.
      • Subpackages like home/ or iconpreview/ contain Composables specific to those features.
    • destination/: Each feature has its own subpackage containing both the screen Composable and its ViewModel (for example, home/Home.kt + home/HomeViewModel.kt, contributors/Contributors.kt + contributors/ContributorsViewModel.kt).
  • Core Principles:
    • Unidirectional Data Flow (UDF): State (data) flows down from ViewModels to Composables. User actions (events) flow up from Composables to ViewModels.
    • Reactivity: The UI updates automatically when the state it observes changes. We typically use collectAsStateWithLifecycle to listen to StateFlow from ViewModels.
  • Navigation:
    • Lawnicons uses Navigation3 (androidx.navigation3), the typed navigation framework for Compose.
    • Routes are typed Kotlin objects implementing NavKey (for example, Home, About, NewIcons, IconRequest, Contributors, Acknowledgements, DebugMenu).
    • Lawnicons.kt sets up a NavDisplay with an entryProvider block that maps each route to its screen Composable via destination functions (for example, homeDestination(), aboutDestination()).
    • NavigationState.kt manages per-route back stacks using rememberNavBackStack, rememberDecoratedNavEntries, and supports top-level route switching with process-death resilience via rememberSerializable.
    • Navigator.kt provides navigate(route) and goBack() functions that update the NavigationState, handling both top-level route switches and nested back-stack pushes.
  • Responsiveness:
    • The app adapts to different screen sizes. MainActivity.kt calculates isExpandedScreen using WindowWidthSizeClass and WindowHeightSizeClass.
    • Composables like TopAppBar.kt, the home screen's bottom toolbar/FAB, and IconPreviewGrid.kt adjust their layout based on this value.
  • Previews in Android Studio:
    • We use the @PreviewLawnicons custom annotation and SampleData (from ui/util/PreviewUtils.kt) to create effective UI previews.
    • LocalInspectionMode.current helps simplify previews by, for example, avoiding network requests for images.

Important UI components

  • MainActivity.kt: The app's single Activity. It initializes Compose, retrieves MetroViewModelFactory from LawniconsGraph, determines screen size characteristics, and handles the ICON_PICKER_INTENT_ACTION.
  • Lawnicons.kt (in ui/): The root Composable containing the NavDisplay which manages navigation between different screens using Navigation3 and Material motion transitions.
  • NavigationState.kt: Manages saveable back stacks for each top-level route, converting them into decorated NavEntry lists for NavDisplay.
  • Navigator.kt: Encapsulates navigation logic — navigate() for forward navigation and goBack() for back-stack popping.
  • LawniconsScaffold.kt: A common scaffold structure used by most screens, providing a consistent top app bar.
  • IconPreviewGrid.kt: Displays the main grid of icons efficiently using LazyVerticalGrid.

The UI layer is designed to be a presentation layer. It focuses on displaying data provided by ViewModels and capturing user input, delegating business logic to the ViewModels.

Clone this wiki locally