An interactive Jetpack Compose starter project demonstrating state hoisting, survival across configuration changes with
rememberSaveable, spring-physics list animations, and Material 3 design systems.
The Compose-BasicCodeLab project demonstrates fundamental paradigm shifts introduced by Jetpack Compose. Unlike imperative Android UI toolkits that mutate existing view trees, this application showcases declarative UI rendering, where the interface is a direct mathematical function of state ($UI = f(State)$).
- Unidirectional Data Flow (UDF): Understanding how state flows down and events flow up through composable hierarchies.
- State Hoisting: Promoting state to common ancestors (
MyApp) to decouple business logic and make composables stateless, reusable, and easily testable. - Configuration Survival: Leveraging
rememberSaveableto retain UI state (such as onboarding status and card expansion) across device rotations and process recreations. - Physics-Based UI Animations: Utilizing Jetpack Compose's
animateContentSizewith customizedspringspecs (DampingRatioMediumBouncyandStiffnessLow). - High-Performance Lists: Rendering virtualized collections containing 1,000+ dynamic items via
LazyColumn.
graph TD
classDef state fill:#1A365D,stroke:#63B3ED,stroke-width:2px,color:#fff;
classDef comp fill:#2D3748,stroke:#4FD1C5,stroke-width:2px,color:#fff;
classDef event fill:#744210,stroke:#F6E05E,stroke-width:2px,color:#fff;
subgraph StateManagement ["Root State Hoisting (MyApp)"]
StateOnboard["shouldShowOnboarding: Boolean<br/>(rememberSaveable)"]:::state
end
StateOnboard -->|true| OnboardingScreen["OnboardingScreen()"]:::comp
StateOnboard -->|false| GreetingsScreen["Greetings()"]:::comp
OnboardingScreen -->|User clicks 'Continue'| EventContinue["onContinueClicked()"]:::event
EventContinue -->|Mutates state to false| StateOnboard
GreetingsScreen --> LazyList["LazyColumn(1000 items)"]:::comp
LazyList --> GreetingCard["Greeting(name)"]:::comp
subgraph CardComponent ["CardContents (Internal Component State)"]
CardState["expanded: Boolean<br/>(rememberSaveable)"]:::state
SpringAnim["animateContentSize(spring: Bouncy)"]:::comp
CardState --> SpringAnim
end
GreetingCard --> CardComponent
CardComponent -->|Toggle expanded| CardState
State is elevated to MyApp, allowing seamless transitions between the Onboarding screen and the Greeting feed:
@Composable
funMyApp(modifier:Modifier = Modifier) {
var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }
Surface(modifier, color =MaterialTheme.colorScheme.background) {
if (shouldShowOnboarding) {
OnboardingScreen(onContinueClicked = { shouldShowOnboarding =false })
} else {
Greetings()
}
}
}Cards dynamically expand to show detailed text with a fluid spring oscillation curve:
@Composable
funCardContents(name:String) {
var expanded by rememberSaveable { mutableStateOf(false) }
Row(
modifier =Modifier
.padding(12.dp)
.animateContentSize(
animationSpec = spring(
dampingRatio =Spring.DampingRatioMediumBouncy,
stiffness =Spring.StiffnessLow
)
)
) {
Column(
modifier =Modifier
.weight(1f)
.padding(12.dp)
) {
Text(text ="Hello ")
Text(
text = name,
style =MaterialTheme.typography.headlineMedium.copy(fontWeight =FontWeight.Bold)
)
if (expanded) {
Text(
text = ("Compose ipsum colors sit smoothly, padding themes elegantly... ").repeat(4)
)
}
}
IconButton(onClick = { expanded =!expanded }) {
Icon(
imageVector =if (expanded) Icons.Filled.ExpandLesselseIcons.Filled.ExpandMore,
contentDescription =if (expanded) stringResource(R.string.show_less) else stringResource(R.string.show_more)
)
}
}
}Replaces legacy RecyclerView adapters and view holders with a single declarative construct that efficiently emits visible items on demand.
Pre-configured with light and dark mode @Preview definitions, verifying UI contrast and typography across form factors.
Compose-BasicCodeLab/
├── app/
│ ├── src/main/java/com/example/basiccodelab/
│ │ ├── MainActivity.kt # Host Activity, Onboarding & Greeting Composables
│ │ └── ui/theme/
│ │ ├── Color.kt # Material 3 Color tokens (Purple / Blue variants)
│ │ ├── Theme.kt # BasicCodeLabTheme wrapper & dynamic color logic
│ │ └── Type.kt # Custom Typography hierarchy
│ ├── src/main/res/
│ │ ├── drawable/ # Vector drawables & launcher icons
│ │ └── values/ # Localized string keys (show_more, show_less)
│ └── build.gradle.kts # Kotlin DSL Gradle build script & Compose BOM
└── gradle/
└── libs.versions.toml # Version Catalog for dependencies & plugins
| Component | Library / Framework | Version / Notes |
|---|---|---|
| Platform | Android | API 24+ (Target SDK 35, Compile SDK 35) |
| Language | Kotlin | 2.0+ with Kotlin Compose Compiler Plugin |
| UI Toolkit | Jetpack Compose | Compose BOM (androidx.compose:compose-bom) |
| Design System | Material Design 3 | androidx.compose.material3:material3 |
| Animation Engine | Compose Animation Core | Physics-based spring animations |
| Architecture | Unidirectional Data Flow | State hoisting & rememberSaveable |
| Tooling | Android Studio Preview | Multipreview (Light & Dark theme variants) |
- Android Studio Ladybug (2024.2.1+) or newer.
- JDK 17 or JDK 21.
- Android SDK 35.
- Clone the repository:
git clone https://github.com/shayann07/Compose-BasicCodeLab.git cd Compose-BasicCodeLab - Open in Android Studio: Open the folder and allow Gradle to complete dependency resolution.
- Execute Build:
./gradlew assembleDebug
- Deploy: Run on an emulator or physical device running Android 7.0 (Nougat) or higher.
This project is licensed under the MIT License — Copyright (c) 2026 shayann07.