diff --git a/app/build.gradle b/app/build.gradle index 9eed9ae..48c9178 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { defaultConfig { applicationId "com.example.tiptime" - minSdk 21 + minSdk 24 targetSdk 33 versionCode 1 versionName "1.0" @@ -48,22 +48,20 @@ android { dependencies { - // Import the Compose BOM - def composeBom = platform('androidx.compose:compose-bom:2023.01.00') - implementation composeBom - androidTestImplementation composeBom - + implementation platform('androidx.compose:compose-bom:2023.01.00') + implementation 'androidx.activity:activity-compose:1.6.1' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'com.google.android.material:material:1.8.0' - implementation 'androidx.activity:activity-compose:1.6.1' - implementation "androidx.compose.ui:ui" - implementation "androidx.compose.material:material" - implementation "androidx.compose.ui:ui-tooling-preview" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' - implementation 'androidx.activity:activity-compose:1.6.1' + implementation 'androidx.compose.ui:ui' + implementation 'androidx.compose.material3:material3' + implementation 'androidx.compose.ui:ui-tooling-preview' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0' + testImplementation 'junit:junit:4.13.2' + + androidTestImplementation platform('androidx.compose:compose-bom:2023.01.00') androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - androidTestImplementation "androidx.compose.ui:ui-test-junit4" - debugImplementation "androidx.compose.ui:ui-test-manifest" -} \ No newline at end of file + androidTestImplementation 'androidx.compose.ui:ui-test-junit4' + + debugImplementation 'androidx.compose.ui:ui-test-manifest' +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 44314b6..f12a697 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,22 @@ - + + + + android:theme="@style/Theme.TipTime" + tools:targetApi="33"> @@ -20,4 +39,4 @@ - \ No newline at end of file + diff --git a/app/src/main/java/com/example/tiptime/MainActivity.kt b/app/src/main/java/com/example/tiptime/MainActivity.kt index a9640ae..92bf8fd 100644 --- a/app/src/main/java/com/example/tiptime/MainActivity.kt +++ b/app/src/main/java/com/example/tiptime/MainActivity.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,176 +18,27 @@ package com.example.tiptime import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.annotation.StringRes -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.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.Surface -import androidx.compose.material.Switch -import androidx.compose.material.SwitchDefaults -import androidx.compose.material.Text -import androidx.compose.material.TextField +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusDirection -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.example.tiptime.ui.theme.TipTimeTheme -import java.text.NumberFormat class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { TipTimeTheme { - Surface(modifier = Modifier.fillMaxSize()) { - TipTimeScreen() + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { } } } } } - -@Composable -fun TipTimeScreen() { - var amountInput by remember { mutableStateOf("") } - var tipInput by remember { mutableStateOf("") } - var roundUp by remember { mutableStateOf(false) } - - val amount = amountInput.toDoubleOrNull() ?: 0.0 - val tipPercent = tipInput.toDoubleOrNull() ?: 0.0 - val tip = calculateTip(amount, tipPercent, roundUp) - - val focusManager = LocalFocusManager.current - - Column( - modifier = Modifier.padding(32.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text( - text = stringResource(R.string.calculate_tip), - fontSize = 24.sp, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - Spacer(Modifier.height(16.dp)) - EditNumberField( - label = R.string.bill_amount, - keyboardOptions = KeyboardOptions.Default.copy( - keyboardType = KeyboardType.Number, - imeAction = ImeAction.Next - ), - keyboardActions = KeyboardActions( - onNext = { focusManager.moveFocus(FocusDirection.Down) } - ), - value = amountInput, - onValueChanged = { amountInput = it } - ) - EditNumberField( - label = R.string.how_was_the_service, - keyboardOptions = KeyboardOptions.Default.copy( - keyboardType = KeyboardType.Number, - imeAction = ImeAction.Done - ), - keyboardActions = KeyboardActions( - onDone = { focusManager.clearFocus() } - ), - value = tipInput, - onValueChanged = { tipInput = it } - ) - RoundTheTipRow(roundUp = roundUp, onRoundUpChanged = { roundUp = it }) - Spacer(Modifier.height(24.dp)) - Text( - text = stringResource(R.string.tip_amount, tip), - modifier = Modifier.align(Alignment.CenterHorizontally), - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - } -} - -@Composable -fun EditNumberField( - @StringRes label: Int, - keyboardOptions: KeyboardOptions, - keyboardActions: KeyboardActions, - value: String, - onValueChanged: (String) -> Unit, - modifier: Modifier = Modifier -) { - TextField( - value = value, - singleLine = true, - modifier = modifier.fillMaxWidth(), - onValueChange = onValueChanged, - label = { Text(stringResource(label)) }, - keyboardOptions = keyboardOptions, - keyboardActions = keyboardActions - ) -} - -@Composable -fun RoundTheTipRow( - roundUp: Boolean, - onRoundUpChanged: (Boolean) -> Unit, - modifier: Modifier = Modifier -) { - Row( - modifier = Modifier - .fillMaxWidth() - .size(48.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = stringResource(R.string.round_up_tip)) - Switch( - modifier = modifier - .fillMaxWidth() - .wrapContentWidth(Alignment.End), - checked = roundUp, - onCheckedChange = onRoundUpChanged, - colors = SwitchDefaults.colors( - uncheckedThumbColor = Color.DarkGray - ) - ) - } -} - -/** - * Calculates the tip based on the user input and format the tip amount - * according to the local currency and display it onscreen. - * Example would be "$10.00". - */ -private fun calculateTip(amount: Double, tipPercent: Double = 15.0, roundUp: Boolean): String { - var tip = tipPercent / 100 * amount - if (roundUp) - tip = kotlin.math.ceil(tip) - return NumberFormat.getCurrencyInstance().format(tip) -} - -@Preview -@Composable -fun TipTimeScreenPreview() { - TipTimeTheme { - TipTimeScreen() - } -} diff --git a/app/src/main/java/com/example/tiptime/ui/theme/Color.kt b/app/src/main/java/com/example/tiptime/ui/theme/Color.kt index a7d1f4e..a2eea2a 100644 --- a/app/src/main/java/com/example/tiptime/ui/theme/Color.kt +++ b/app/src/main/java/com/example/tiptime/ui/theme/Color.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,10 @@ package com.example.tiptime.ui.theme import androidx.compose.ui.graphics.Color -val Purple200 = Color(0xFFBB86FC) -val Purple500 = Color(0xFF6200EE) -val Purple700 = Color(0xFF3700B3) -val Teal200 = Color(0xFF03DAC5) +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/example/tiptime/ui/theme/Shape.kt b/app/src/main/java/com/example/tiptime/ui/theme/Shape.kt deleted file mode 100644 index 34e53ec..0000000 --- a/app/src/main/java/com/example/tiptime/ui/theme/Shape.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.tiptime.ui.theme - -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Shapes -import androidx.compose.ui.unit.dp - -val Shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) -) diff --git a/app/src/main/java/com/example/tiptime/ui/theme/Theme.kt b/app/src/main/java/com/example/tiptime/ui/theme/Theme.kt index 1033e87..d261922 100644 --- a/app/src/main/java/com/example/tiptime/ui/theme/Theme.kt +++ b/app/src/main/java/com/example/tiptime/ui/theme/Theme.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,36 +15,61 @@ */ package com.example.tiptime.ui.theme +import android.app.Activity +import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.MaterialTheme -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat -private val DarkColorPalette = darkColors( - primary = Purple200, - primaryVariant = Purple700, - secondary = Teal200 +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 ) -private val LightColorPalette = lightColors( - primary = Purple500, - primaryVariant = Purple700, - secondary = Teal200 +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 ) @Composable -fun TipTimeTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { - val colors = if (darkTheme) { - DarkColorPalette - } else { - LightColorPalette +fun TipTimeTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } } MaterialTheme( - colors = colors, + colorScheme = colorScheme, typography = Typography, - shapes = Shapes, content = content ) } diff --git a/app/src/main/java/com/example/tiptime/ui/theme/Type.kt b/app/src/main/java/com/example/tiptime/ui/theme/Type.kt index 263cef7..7d1d940 100644 --- a/app/src/main/java/com/example/tiptime/ui/theme/Type.kt +++ b/app/src/main/java/com/example/tiptime/ui/theme/Type.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ package com.example.tiptime.ui.theme -import androidx.compose.material.Typography +import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight @@ -23,9 +23,11 @@ import androidx.compose.ui.unit.sp // Set of Material typography styles to start with val Typography = Typography( - body1 = TextStyle( + bodyLarge = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.Normal, - fontSize = 16.sp + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp ) ) \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml index 793e74f..96fbfa9 100644 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -1,19 +1,19 @@ + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index eca70cf..001bfd9 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,4 +1,20 @@ + + diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml deleted file mode 100644 index 371aa87..0000000 --- a/app/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - -