From 14f13dd91240b7d964ffd4f209d21ff0ec3d4984 Mon Sep 17 00:00:00 2001 From: John Shea Date: Mon, 23 Oct 2023 14:34:26 -0400 Subject: [PATCH 1/4] Update versions to the latest --- app/build.gradle.kts | 18 +++++++++--------- build.gradle.kts | 8 ++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 924a7ac..28abb3d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,12 +20,12 @@ plugins { android { namespace = "com.example.cupcake" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "com.example.cupcake" minSdk = 24 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" @@ -56,7 +56,7 @@ android { compose = true } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.3" } packaging { resources { @@ -67,24 +67,24 @@ android { dependencies { - implementation(platform("androidx.compose:compose-bom:2023.05.01")) - implementation("androidx.activity:activity-compose:1.7.2") + implementation(platform("androidx.compose:compose-bom:2023.10.01")) + implementation("androidx.activity:activity-compose:1.8.0") implementation("androidx.compose.material3:material3") implementation("androidx.compose.runtime:runtime") implementation("androidx.compose.runtime:runtime-livedata") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.lifecycle:lifecycle-livedata-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-runtime-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:${rootProject.extra["lifecycle_version"]}") - implementation("androidx.navigation:navigation-compose:2.6.0") + implementation("androidx.navigation:navigation-compose:2.7.4") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.05.01")) + androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") - androidTestImplementation("androidx.navigation:navigation-testing:2.6.0") + androidTestImplementation("androidx.navigation:navigation-testing:2.7.4") androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1") androidTestImplementation("androidx.test.ext:junit:1.1.5") diff --git a/build.gradle.kts b/build.gradle.kts index 3a8f034..02c3cc7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,11 +16,11 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { extra.apply { - set("lifecycle_version", "2.6.1") + set("lifecycle_version", "2.6.2") } } plugins { - id("com.android.application") version "8.0.2" apply false - id("com.android.library") version "8.0.2" apply false - id("org.jetbrains.kotlin.android") version "1.8.21" apply false + id("com.android.application") version "8.1.2" apply false + id("com.android.library") version "8.1.2" apply false + id("org.jetbrains.kotlin.android") version "1.9.10" apply false } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3148757..d626975 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Mar 19 17:30:22 PDT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 1c31d367a1ce00b13962b1133c896ca570e97142 Mon Sep 17 00:00:00 2001 From: John Shea Date: Tue, 24 Oct 2023 11:45:13 -0400 Subject: [PATCH 2/4] Implement edge-to-edge --- app/src/main/java/com/example/cupcake/MainActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/cupcake/MainActivity.kt b/app/src/main/java/com/example/cupcake/MainActivity.kt index 22b231a..e71fc31 100644 --- a/app/src/main/java/com/example/cupcake/MainActivity.kt +++ b/app/src/main/java/com/example/cupcake/MainActivity.kt @@ -18,13 +18,13 @@ package com.example.cupcake import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.core.view.WindowCompat +import androidx.activity.enableEdgeToEdge import com.example.cupcake.ui.theme.CupcakeTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() super.onCreate(savedInstanceState) - WindowCompat.setDecorFitsSystemWindows(window, false) setContent { CupcakeTheme { CupcakeApp() From 5b8dab87ee59f02aafb948506f3a3a25e46ebcea Mon Sep 17 00:00:00 2001 From: John Shea Date: Wed, 25 Oct 2023 11:58:33 -0400 Subject: [PATCH 3/4] Implement vertical scrolling for landscape orientation --- .../java/com/example/cupcake/CupcakeScreen.kt | 7 ++- .../example/cupcake/ui/SelectOptionScreen.kt | 29 ++++++----- .../example/cupcake/ui/StartOrderScreen.kt | 48 ++++++++++--------- .../com/example/cupcake/ui/SummaryScreen.kt | 23 ++++----- 4 files changed, 60 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/com/example/cupcake/CupcakeScreen.kt b/app/src/main/java/com/example/cupcake/CupcakeScreen.kt index dbb1e8c..86e8eaf 100644 --- a/app/src/main/java/com/example/cupcake/CupcakeScreen.kt +++ b/app/src/main/java/com/example/cupcake/CupcakeScreen.kt @@ -21,6 +21,8 @@ import androidx.annotation.StringRes import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.Icon @@ -115,7 +117,10 @@ fun CupcakeApp( NavHost( navController = navController, startDestination = CupcakeScreen.Start.name, - modifier = Modifier.padding(innerPadding) + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(innerPadding) ) { composable(route = CupcakeScreen.Start.name) { StartOrderScreen( diff --git a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt index a5d7df1..2f64572 100644 --- a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.example.cupcake.R import com.example.cupcake.ui.components.FormattedPriceLabel +import com.example.cupcake.ui.theme.CupcakeTheme /** * Composable that displays the list of items as [RadioButton] options, @@ -54,7 +55,7 @@ fun SelectOptionScreen( onCancelButtonClicked: () -> Unit = {}, onNextButtonClicked: () -> Unit = {}, modifier: Modifier = Modifier -){ +) { var selectedValue by rememberSaveable { mutableStateOf("") } Column( @@ -72,7 +73,7 @@ fun SelectOptionScreen( } ), verticalAlignment = Alignment.CenterVertically - ){ + ) { RadioButton( selected = selectedValue == item, onClick = { @@ -100,12 +101,14 @@ fun SelectOptionScreen( Row( modifier = Modifier .fillMaxWidth() - .padding(dimensionResource(R.dimen.padding_medium)) - .weight(1f, false), + .padding(dimensionResource(R.dimen.padding_medium)), horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_medium)), verticalAlignment = Alignment.Bottom - ){ - OutlinedButton(modifier = Modifier.weight(1f), onClick = onCancelButtonClicked) { + ) { + OutlinedButton( + modifier = Modifier.weight(1f), + onClick = onCancelButtonClicked + ) { Text(stringResource(R.string.cancel)) } Button( @@ -123,10 +126,12 @@ fun SelectOptionScreen( @Preview @Composable -fun SelectOptionPreview(){ - SelectOptionScreen( - subtotal = "299.99", - options = listOf("Option 1", "Option 2", "Option 3", "Option 4"), - modifier = Modifier.fillMaxHeight() - ) +fun SelectOptionPreview() { + CupcakeTheme { + SelectOptionScreen( + subtotal = "299.99", + options = listOf("Option 1", "Option 2", "Option 3", "Option 4"), + modifier = Modifier.fillMaxHeight() + ) + } } diff --git a/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt b/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt index 036b29d..6b9c833 100644 --- a/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt @@ -19,9 +19,7 @@ import androidx.annotation.StringRes import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -41,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.cupcake.R import com.example.cupcake.data.DataSource +import com.example.cupcake.ui.theme.CupcakeTheme /** * Composable that allows the user to select the desired cupcake quantity and expects @@ -52,7 +51,7 @@ fun StartOrderScreen( quantityOptions: List>, onNextButtonClicked: (Int) -> Unit, modifier: Modifier = Modifier -){ +) { Column( modifier = modifier, verticalArrangement = Arrangement.SpaceBetween @@ -75,20 +74,19 @@ fun StartOrderScreen( ) Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small))) } - Row(modifier = Modifier.weight(1f, false)) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy( - dimensionResource(id = R.dimen.padding_medium) + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy( + dimensionResource(id = R.dimen.padding_medium) + ) + ) { + quantityOptions.forEach { item -> + SelectQuantityButton( + labelResourceId = item.first, + onClick = { onNextButtonClicked(item.second) }, + modifier = Modifier.fillMaxWidth(), ) - ) { - quantityOptions.forEach { item -> - SelectQuantityButton( - labelResourceId = item.first, - onClick = { onNextButtonClicked(item.second) } - ) - } } } } @@ -103,7 +101,7 @@ fun SelectQuantityButton( @StringRes labelResourceId: Int, onClick: () -> Unit, modifier: Modifier = Modifier -){ +) { Button( onClick = onClick, modifier = modifier.widthIn(min = 250.dp) @@ -114,10 +112,14 @@ fun SelectQuantityButton( @Preview @Composable -fun StartOrderPreview(){ - StartOrderScreen( - quantityOptions = DataSource.quantityOptions, - onNextButtonClicked = {}, - modifier = Modifier.fillMaxSize().padding(dimensionResource(R.dimen.padding_medium)) - ) +fun StartOrderPreview() { + CupcakeTheme { + StartOrderScreen( + quantityOptions = DataSource.quantityOptions, + onNextButtonClicked = {}, + modifier = Modifier + .fillMaxSize() + .padding(dimensionResource(R.dimen.padding_medium)) + ) + } } diff --git a/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt b/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt index cd8c75a..1fae196 100644 --- a/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview import com.example.cupcake.R import com.example.cupcake.data.OrderUiState import com.example.cupcake.ui.components.FormattedPriceLabel +import com.example.cupcake.ui.theme.CupcakeTheme /** * This composable expects [orderUiState] that represents the order state, [onCancelButtonClicked] @@ -50,7 +51,7 @@ fun OrderSummaryScreen( onCancelButtonClicked: () -> Unit, onSendButtonClicked: (String, String) -> Unit, modifier: Modifier = Modifier -){ +) { val resources = LocalContext.current.resources val numberOfCupcakes = resources.getQuantityString( @@ -97,9 +98,7 @@ fun OrderSummaryScreen( ) } Row( - modifier = Modifier - .weight(1f, false) - .padding(dimensionResource(R.dimen.padding_medium)) + modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium)) ) { Column( verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_small)) @@ -123,11 +122,13 @@ fun OrderSummaryScreen( @Preview @Composable -fun OrderSummaryPreview(){ - OrderSummaryScreen( - orderUiState = OrderUiState(0, "Test", "Test", "$300.00"), - onSendButtonClicked = { subject: String, summary: String -> }, - onCancelButtonClicked = {}, - modifier = Modifier.fillMaxHeight() - ) +fun OrderSummaryPreview() { + CupcakeTheme { + OrderSummaryScreen( + orderUiState = OrderUiState(0, "Test", "Test", "$300.00"), + onSendButtonClicked = { subject: String, summary: String -> }, + onCancelButtonClicked = {}, + modifier = Modifier.fillMaxHeight() + ) + } } From 8f9aedaebca80363480c7be79794120e67c90889 Mon Sep 17 00:00:00 2001 From: John Shea Date: Wed, 1 Nov 2023 11:44:41 -0400 Subject: [PATCH 4/4] Remove TODO wording from README.md --- README.md | 3 --- app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index ae1ae2e..205382e 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,12 @@ This app contains an order flow for cupcakes with options for quantity, flavor, The order details get displayed on an order summary screen and can be shared to another app to send the order. -TODO - Pre-requisites -------------- * Experience with Kotlin syntax. * How to create and run a project in Android Studio. * How to create composable functions -* TODO Getting Started diff --git a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt index 2f64572..4420efd 100644 --- a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt @@ -62,7 +62,7 @@ fun SelectOptionScreen( modifier = modifier, verticalArrangement = Arrangement.SpaceBetween ) { - Column(modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))){ + Column(modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))) { options.forEach { item -> Row( modifier = Modifier.selectable(