Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
561f734
refactor: migrate Room annotation processing from KAPT to KSP
Jun 6, 2026
516a461
feat: upgrade Kotlin to 2.1.20 with the K2 compiler
Jun 6, 2026
0279224
style: bump ktfmt-gradle to 0.22.0 and reformat
Jun 7, 2026
d45b54d
feat: bump compileSdk and targetSdk to 35 (Android 15)
Jun 6, 2026
0323bca
feat: adopt the Compose BOM (2024.12.01) for unified version management
Jun 7, 2026
b3e191b
feat: upgrade AndroidX Lifecycle to 2.8.7
Jun 7, 2026
afc9f0b
feat: upgrade Navigation Compose to 2.8.9 with type-safe routes
Jun 7, 2026
1ade1c9
refactor: migrate from ExoPlayer 2.x to AndroidX Media3 1.5.1
Jun 7, 2026
229d33d
feat: upgrade Coil to 3.1.0
Jun 7, 2026
ffcbcb5
feat: implement Pull-to-Refresh demo with Material3 PullToRefreshBox
Jun 7, 2026
368f005
feat: complete Swipe-to-Dismiss demo with delete/archive actions and …
Jun 7, 2026
0f14efd
feat: add adaptive layout / large screen demo
Jun 7, 2026
8be0dcc
feat: add infinite looping carousel with auto-advance
Jun 7, 2026
927c9b1
test: add Compose UI tests to tags, carousel and login modules
Jun 7, 2026
2eb1653
refactor: migrate dependency management to a Gradle version catalog
Jun 7, 2026
d37b8c6
chore: refresh foundational dependencies to SDK-35-compatible baselines
Jun 14, 2026
008db74
feat: add Predictive Back gesture demo for Android 15+
Jun 14, 2026
c33a52f
feat: add contrast-aware Material 3 theme demo
Jun 14, 2026
84c7132
feat: add Shared Element / Shared Bounds transitions demo
Jun 14, 2026
fdd1040
test: add Roborazzi screenshot testing on the tags module
Jun 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<a href="https://github.com/Gurupreet/ComposeCookBook/releases/download/latest-master/app-debug.apk" >
<img src = "https://img.shields.io/badge/Master-Master?color=7885FF&label=Sample%20App&logo=android&style=for-the-badge" />
</a>
<a href = "https://developer.android.com/jetpack/androidx/versions/all-channel#december_16_2020">
<img src = "https://img.shields.io/badge/Jetpack%20Compose-1.0.1-brightgreen" />
<a href = "https://developer.android.com/develop/ui/compose/bom/bom-mapping">
<img src = "https://img.shields.io/badge/Jetpack%20Compose-BOM%202024.12.01-brightgreen" />
</a>
<a href = "https://github.com/Gurupreet/ComposeCookBook/actions/workflows/android.yml">
<img src = "https://github.com/Gurupreet/ComposeCookBook/actions/workflows/android.yml/badge.svg" />
Expand Down Expand Up @@ -100,9 +100,12 @@ Please get **Android Studio Bumblebee latest Canary** [from here](https://develo
- __Others:__ After the above steps feel free to deep dive into Tablayouts, carousel, Dialogs and BottomSheets


### Adaptive layouts (large screens)
- `NavigationSuiteScaffold` switches between bottom bar, rail and drawer based on window size
- `ListDetailPaneScaffold` two-pane layout on tablets/foldables — find it under "Adaptive UI" on the home screen

## Coming Soon
- Some of the features that will be available in coming weeks
- Advance lists: Pull Refresh, Swipe lists etc
- Clean Architecture Sample with coroutines.
- Advance canvas drawing.
Much more in pipeline stay tuned!!
Expand Down
17 changes: 6 additions & 11 deletions animations/canvas/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import com.guru.composecookbook.build.dependencies.addComposeOfficialDependencies

plugins {
/**
* See [common-compose-module-configs-script-plugin.gradle.kts] file
*/
id("common-compose-module-configs-script-plugin")
/** See [common-compose-module-configs-script-plugin.gradle.kts] file */
id("common-compose-module-configs-script-plugin")
}

android {
namespace = "com.guru.composecookbook.canvas"
}
android { namespace = "com.guru.composecookbook.canvas" }

dependencies {
implementation(project(":theme"))
addComposeOfficialDependencies()
implementation(project(":theme"))
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.compose.official)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,12 @@ fun MultiStateAnimationCircleFilledCanvas(color: Color = green500, radiusEnd: Fl
transition.animateFloat(
initialValue = 10f,
targetValue = radiusEnd,
animationSpec = infiniteRepeatable(tween(1200), RepeatMode.Reverse)
animationSpec = infiniteRepeatable(tween(1200), RepeatMode.Reverse),
)
Canvas(modifier = Modifier.padding(16.dp)) {
val centerOffset = Offset(10f, 10f)
drawCircle(
color = color.copy(alpha = 0.8f),
radius = floatAnim,
center = centerOffset,
)
drawCircle(
color = color.copy(alpha = 0.4f),
radius = floatAnim / 2,
center = centerOffset,
)
drawCircle(
color = color.copy(alpha = 0.2f),
radius = floatAnim / 4,
center = centerOffset,
)
drawCircle(color = color.copy(alpha = 0.8f), radius = floatAnim, center = centerOffset)
drawCircle(color = color.copy(alpha = 0.4f), radius = floatAnim / 2, center = centerOffset)
drawCircle(color = color.copy(alpha = 0.2f), radius = floatAnim / 4, center = centerOffset)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fun MultiStateAnimationCircleStrokeCanvas() {
transition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(tween(800), RepeatMode.Restart)
animationSpec = infiniteRepeatable(tween(800), RepeatMode.Restart),
)
val stroke = Stroke(8f)
Canvas(modifier = Modifier.padding(16.dp).size(100.dp)) {
Expand Down
21 changes: 7 additions & 14 deletions animations/lottie/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import com.guru.composecookbook.build.dependencies.addComposeOfficialDependencies
import com.guru.composecookbook.build.dependencies.addCoreAndroidDependencies
import com.guru.composecookbook.build.dependencies.addThirdPartyUiDependencies

plugins {
/**
* See [common-compose-module-configs-script-plugin.gradle.kts] file
*/
id("common-compose-module-configs-script-plugin")
/** See [common-compose-module-configs-script-plugin.gradle.kts] file */
id("common-compose-module-configs-script-plugin")
}

android {
namespace = "com.guru.composecookbook.lottie"
}
android { namespace = "com.guru.composecookbook.lottie" }

dependencies {
addComposeOfficialDependencies()
addCoreAndroidDependencies()
addThirdPartyUiDependencies()
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.compose.official)
implementation(libs.bundles.core.android)
implementation(libs.bundles.thirdparty.ui)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ fun LottieCryptoLoadingView(context: Context) {
LottieLoadingView(
context = context,
file = "cryptoload.json",
modifier = Modifier.fillMaxWidth().height(150.dp)
modifier = Modifier.fillMaxWidth().height(150.dp),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ fun LottieFoodView(context: Context) {
LottieLoadingView(
context = context,
file = "food.json",
modifier = Modifier.fillMaxWidth().height(200.dp)
modifier = Modifier.fillMaxWidth().height(200.dp),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ fun LottieLoaderLoadingView(context: Context) {
LottieLoadingView(
context = context,
file = "loader.json",
modifier = Modifier.fillMaxWidth().height(200.dp)
modifier = Modifier.fillMaxWidth().height(200.dp),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fun LottieLoadingView(
context: Context,
file: String,
modifier: Modifier = Modifier,
iterations: Int = 10
iterations: Int = 10,
) {
val composition by rememberLottieComposition(LottieCompositionSpec.Asset(file))
LottieAnimation(composition, modifier = modifier.defaultMinSize(300.dp), iterations = iterations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ fun LottieWorkingLoadingView(context: Context) {
LottieLoadingView(
context = context,
file = "working.json",
modifier = Modifier.fillMaxWidth().height(250.dp)
modifier = Modifier.fillMaxWidth().height(250.dp),
)
}
190 changes: 81 additions & 109 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,128 +1,100 @@
import com.guru.composecookbook.build.configurations.ProjectConfigs
import com.guru.composecookbook.build.dependencies.addAndroidInstrumentationTestsDependencies
import com.guru.composecookbook.build.dependencies.addBiometricDependency
import com.guru.composecookbook.build.dependencies.addComposeDebugDependencies
import com.guru.composecookbook.build.dependencies.addComposeOfficialDependencies
import com.guru.composecookbook.build.dependencies.addComposeThirdPartyDependencies
import com.guru.composecookbook.build.dependencies.addCoreAndroidDependencies
import com.guru.composecookbook.build.dependencies.addCoreAndroidUiDependencies
import com.guru.composecookbook.build.dependencies.addDataDependencies
import com.guru.composecookbook.build.dependencies.addGoogleAndroidDependencies
import com.guru.composecookbook.build.dependencies.addJunit5TestDependencies
import com.guru.composecookbook.build.dependencies.addKotlinDependencies
import com.guru.composecookbook.build.dependencies.addKotlinTestDependencies
import com.guru.composecookbook.build.dependencies.addNetworkingDependencies
import com.guru.composecookbook.build.dependencies.addThirdPartyUiDependencies
import com.guru.composecookbook.build.dependencies.addThirdPartyUnitTestsDependencies

plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-kapt")
id("com.android.application")
id("kotlin-android")
id("com.google.devtools.ksp")
id("org.jetbrains.kotlin.plugin.compose")
}

android {
compileSdk = ProjectConfigs.compileSdkVersion
namespace = ProjectConfigs.applicationId

compileSdk = ProjectConfigs.compileSdkVersion
namespace = ProjectConfigs.applicationId
defaultConfig {
applicationId = ProjectConfigs.applicationId
minSdk = ProjectConfigs.minSdkVersion
targetSdk = ProjectConfigs.targetSdkVersion
versionCode = 1
versionName = "1.0"
multiDexEnabled = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

defaultConfig {
applicationId = ProjectConfigs.applicationId
minSdk = ProjectConfigs.minSdkVersion
targetSdk = ProjectConfigs.targetSdkVersion
versionCode = 1
versionName = "1.0"
multiDexEnabled = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
// useIR = true
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"

}
kapt {
correctErrorTypes = true
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = ProjectConfigs.kotlinCompilerExtensionVersion
}
lint {
abortOnError = false
}
testOptions {
unitTests.all {
it.useJUnitPlatform()
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
// useIR = true
freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.RequiresOptIn"
}
buildFeatures { compose = true }
lint { abortOnError = false }
testOptions { unitTests.all { it.useJUnitPlatform() } }
}

dependencies {
implementation(project(":data"))
implementation(project(":theme"))
implementation(project(":demos:instagram"))
implementation(project(":demos:spotify"))
implementation(project(":demos:twitter"))
implementation(project(":demos:tiktok"))
implementation(project(":demos:youtube"))
implementation(project(":demos:gmail"))
implementation(project(":demos:datingapp"))
implementation(project(":demos:paint"))
implementation(project(":demos:cryptoapp:app"))
implementation(project(":demos:moviesapp:app"))
implementation(project(":demos:meditation"))
implementation(project(":templates:onboarding"))
implementation(project(":templates:paymentcard"))
implementation(project(":templates:pinlock"))
implementation(project(":templates:profile"))
implementation(project(":templates:login"))
implementation(project(":templates:cascademenu"))
implementation(project(":components:fab"))
implementation(project(":components:charts"))
implementation(project(":components:tags"))
implementation(project(":components:carousel"))
implementation(project(":components:verticalgrid"))
implementation(project(":components:colorpicker"))
implementation(project(":components:comingsoon"))
implementation(project(":animations:canvas"))
implementation(project(":animations:lottie"))
implementation(project(":data"))
implementation(project(":theme"))
implementation(project(":demos:instagram"))
implementation(project(":demos:spotify"))
implementation(project(":demos:twitter"))
implementation(project(":demos:tiktok"))
implementation(project(":demos:youtube"))
implementation(project(":demos:gmail"))
implementation(project(":demos:datingapp"))
implementation(project(":demos:paint"))
implementation(project(":demos:cryptoapp:app"))
implementation(project(":demos:moviesapp:app"))
implementation(project(":demos:meditation"))
implementation(project(":templates:onboarding"))
implementation(project(":templates:paymentcard"))
implementation(project(":templates:pinlock"))
implementation(project(":templates:profile"))
implementation(project(":templates:login"))
implementation(project(":templates:cascademenu"))
implementation(project(":components:fab"))
implementation(project(":components:charts"))
implementation(project(":components:tags"))
implementation(project(":components:carousel"))
implementation(project(":components:verticalgrid"))
implementation(project(":components:colorpicker"))
implementation(project(":components:comingsoon"))
implementation(project(":animations:canvas"))
implementation(project(":animations:lottie"))

addKotlinDependencies()
implementation(libs.bundles.kotlin)

addDataDependencies()
implementation(platform(libs.androidx.compose.bom))
ksp(libs.androidx.room.compiler)
implementation(libs.bundles.data)

addComposeOfficialDependencies()
addComposeDebugDependencies()
addComposeThirdPartyDependencies()
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.compose.official)
debugImplementation(platform(libs.androidx.compose.bom))
debugImplementation(libs.bundles.compose.debug)
implementation(libs.bundles.compose.thirdparty)

addThirdPartyUiDependencies()
implementation(libs.bundles.thirdparty.ui)

addCoreAndroidDependencies()
addCoreAndroidUiDependencies()
addGoogleAndroidDependencies()
addNetworkingDependencies()
implementation(libs.bundles.core.android)
implementation(libs.bundles.core.android.ui)
implementation(libs.bundles.google.android)
implementation(libs.bundles.networking)

addKotlinTestDependencies()
addJunit5TestDependencies()
addThirdPartyUnitTestsDependencies()
testImplementation(libs.bundles.kotlin.test)
testImplementation(libs.bundles.junit5.test)
testImplementation(libs.truth)

addAndroidInstrumentationTestsDependencies()
addBiometricDependency()
}
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.bundles.instrumentation.test)
implementation(libs.androidx.biometric)
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class HomeScreenTest {
*/
private fun hasTextInProvidedDemoData(
homeScreenListItems: List<HomeScreenItems>,
ignoreCase: Boolean = false
ignoreCase: Boolean = false,
) =
SemanticsMatcher(
description =
Expand Down
Loading