Compare commits

...

11 Commits

Author SHA1 Message Date
HagaDalpintoGinting
6fe2b76e96 first commit 2025-11-07 18:57:44 +07:00
099c35f19a Update README.md 2025-11-06 12:04:44 +07:00
0ee43c2e9a First update calculation 2025-11-06 11:34:31 +07:00
7053fa6573 First update labels 2025-11-06 11:10:35 +07:00
51c9a8e5ff First commit 2025-11-06 09:58:07 +07:00
renovate[bot]
b029b3dd10
Update all dependencies 8.7.3 to v8.8.0 (#271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 05:25:39 +00:00
renovate[bot]
90545a4a4d
Update dependency gradle 8.11.1 to v8.12 (#263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-21 03:18:17 +00:00
renovate[bot]
e075e6ded8
Update dependency androidx.compose:compose-bom 2024.11.00 to v2024.12.01 (#260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-12 03:31:35 +00:00
Tomáš Mlynarič
7db6c366a3 Update to kotlin 2.1.0 2024-12-09 17:16:15 +01:00
Jose Alcérreca
076428c67e
Merge pull request #257 from google-developer-training/mlykotom-renovate-fix
Add branches to renovate
2024-12-09 13:44:24 +00:00
Tomáš Mlynarič
59c134aec9
Add branches to renovate 2024-12-09 14:35:04 +01:00
13 changed files with 403 additions and 211 deletions

View File

@ -2,5 +2,10 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"local>android/.github:renovate-config" "local>android/.github:renovate-config"
],
"baseBranches": [
"main",
"starter",
"state"
] ]
} }

View File

@ -1,24 +1,10 @@
Tip Time - Solution Code Kalkulator BMI
================================= ===============
Solution code for the [Android Basics with Compose](https://developer.android.com/courses/android-basics-compose/course): Tip Time app. Silahkan kembangkan aplikasi ini untuk melakukan perhitungan BMI
Petunjuk lebih detil dapat dibaca di
https://docs.google.com/document/d/1iGiC0Bg3Bdcd2Maq45TYkCDUkZ5Ql51E/edit?rtpof=true
Introduction Starter dimodifikasi dan terinspirasi dari:
------------ https://developer.android.com/codelabs/basic-android-compose-calculate-tip#0
The Tip Time app contains various UI elements for calculating a tip,
teaching about user input, and State in Compose.
Pre-requisites
--------------
* Experience with Kotlin syntax.
* How to create and run a project in Android Studio.
Getting Started
---------------
1. Install Android Studio, if you don't already have it.
2. Download the sample.
3. Import the sample into Android Studio.
4. Build and run the sample.

View File

@ -1,5 +1,4 @@
/* /* * Copyright (C) 2023 The Android Open Source Project
* Copyright (C) 2023 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,15 +16,17 @@
plugins { plugins {
id("com.android.application") id("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
} }
android { android {
compileSdk = 35 namespace = "com.example.tiptime"
compileSdk = 34
defaultConfig { defaultConfig {
applicationId = "com.example.tiptime" applicationId = "com.example.tiptime"
minSdk = 24 minSdk = 24
targetSdk = 35 targetSdk = 34
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"
@ -55,33 +56,41 @@ android {
compose = true compose = true
} }
composeOptions { composeOptions {
kotlinCompilerExtensionVersion = rootProject.extra["compose_compiler_version"].toString() kotlinCompilerExtensionVersion = "1.5.1"
} }
packaging { packaging {
resources { resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}" excludes += "/META-INF/{AL2.0,LGPL2.1}"
} }
} }
namespace = "com.example.tiptime"
} }
dependencies { dependencies {
implementation(platform("androidx.compose:compose-bom:2024.11.00")) // Gunakan Compose Bill of Materials (BOM) versi stabil
implementation("androidx.activity:activity-compose:1.9.3") val composeBom = platform("androidx.compose:compose-bom:2024.06.00")
implementation(composeBom)
androidTestImplementation(composeBom)
// Dependensi Compose (versi akan diatur oleh BOM)
implementation("androidx.compose.material3:material3") implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling") implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.core:core-ktx:1.15.0") implementation("androidx.compose.foundation:foundation")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
testImplementation("junit:junit:4.13.2") // Dependensi AndroidX lainnya
implementation("androidx.core:core-ktx:1.13.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.11.00")) implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.3")
androidTestImplementation("androidx.compose.ui:ui-test-junit4") implementation("androidx.activity:activity-compose:1.9.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
// Dependensi untuk debug
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest") debugImplementation("androidx.compose.ui:ui-test-manifest")
// Dependensi testing
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
} }

View File

@ -1,18 +1,3 @@
/*
* 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
*
* https://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 package com.example.tiptime
import android.os.Bundle import android.os.Bundle
@ -21,41 +6,31 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
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.safeDrawingPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.*
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource 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.ImeAction
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.tiptime.ui.theme.TipTimeTheme import com.example.tiptime.ui.theme.TipTimeTheme
import java.text.NumberFormat
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -65,132 +40,259 @@ class MainActivity : ComponentActivity() {
TipTimeTheme { TipTimeTheme {
Surface( Surface(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) { ) {
TipTimeLayout() NavigationController()
}
}
}
}
}
// Enum dan NavigationController tetap sama
private sealed class Screen {
object Start : Screen()
object Main : Screen()
}
@Composable
private fun NavigationController() {
var currentScreen by remember { mutableStateOf<Screen>(Screen.Start) }
when (currentScreen) {
is Screen.Start -> {
StartScreen(onNavigateToMain = { currentScreen = Screen.Main })
}
is Screen.Main -> {
BMICalculatorScreen()
}
}
}
// --- INI ADALAH TAMPILAN BARU YANG LEBIH MENARIK ---
@Composable
fun BMICalculatorScreen() {
var heightInput by remember { mutableStateOf("") }
var weightInput by remember { mutableStateOf("") }
var useMetric by remember { mutableStateOf(true) }
val height = heightInput.toDoubleOrNull() ?: 0.0
val weight = weightInput.toDoubleOrNull() ?: 0.0
val bmiValue = calculateBMI(height, weight, useMetric)
val bmiCategory = bmiCategory(bmiValue)
val bmiCategoryColor = getBmiCategoryColor(bmiCategory)
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.safeDrawingPadding()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(R.string.bmi_calculator),
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(vertical = 16.dp)
)
// --- KARTU HASIL BMI ---
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(id = R.string.your_bmi_is),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "%.1f".format(bmiValue),
fontSize = 52.sp,
fontWeight = FontWeight.Bold,
color = bmiCategoryColor
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = bmiCategory,
fontSize = 20.sp,
fontWeight = FontWeight.SemiBold,
color = bmiCategoryColor
)
Spacer(modifier = Modifier.height(16.dp))
BmiIndicatorBar(category = bmiCategory)
}
}
// --- KARTU INPUT DATA ---
Card(
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Column(
modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
UnitSwitchRow(
isMetric = useMetric,
onUnitChanged = { useMetric = it }
)
Spacer(modifier = Modifier.height(24.dp))
val heightLabel = if (useMetric) R.string.height_cm else R.string.height_in
EditNumberField(
label = heightLabel,
leadingIcon = R.drawable.ic_height,
value = heightInput,
onValueChanged = { heightInput = it },
imeAction = ImeAction.Next
)
Spacer(modifier = Modifier.height(16.dp))
val weightLabel = if (useMetric) R.string.weight_kg else R.string.weight_lbs
EditNumberField(
label = weightLabel,
leadingIcon = R.drawable.ic_weight,
value = weightInput,
onValueChanged = { weightInput = it },
imeAction = ImeAction.Done
)
}
}
}
}
@Composable
fun BmiIndicatorBar(category: String) {
val categories = listOf("Underweight", "Normal", "Overweight", "Obese")
Row(
modifier = Modifier
.fillMaxWidth()
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surface)
.padding(2.dp)
) {
categories.forEach { cat ->
Box(
modifier = Modifier
.weight(1f)
.height(12.dp)
.background(
if (cat == category) getBmiCategoryColor(cat) else Color.LightGray.copy(alpha = 0.5f)
)
) {
if (cat == category) {
Text(
text = cat,
color = Color.White,
fontSize = 8.sp, // Ukuran font sangat kecil
textAlign = TextAlign.Center,
modifier = Modifier.align(Alignment.Center)
)
} }
} }
} }
} }
} }
@Composable
fun TipTimeLayout() {
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)
Column(
modifier = Modifier
.statusBarsPadding()
.padding(horizontal = 40.dp)
.verticalScroll(rememberScrollState())
.safeDrawingPadding(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(R.string.calculate_tip),
modifier = Modifier
.padding(bottom = 16.dp, top = 40.dp)
.align(alignment = Alignment.Start)
)
EditNumberField(
label = R.string.bill_amount,
leadingIcon = R.drawable.money,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
value = amountInput,
onValueChanged = { amountInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(),
)
EditNumberField(
label = R.string.how_was_the_service,
leadingIcon = R.drawable.percent,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
value = tipInput,
onValueChanged = { tipInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(),
)
RoundTheTipRow(
roundUp = roundUp,
onRoundUpChanged = { roundUp = it },
modifier = Modifier.padding(bottom = 32.dp)
)
Text(
text = stringResource(R.string.tip_amount, tip),
style = MaterialTheme.typography.displaySmall
)
Spacer(modifier = Modifier.height(150.dp))
}
}
@Composable @Composable
fun EditNumberField( fun EditNumberField(
@StringRes label: Int, @StringRes label: Int,
@DrawableRes leadingIcon: Int, @DrawableRes leadingIcon: Int,
keyboardOptions: KeyboardOptions,
value: String, value: String,
onValueChanged: (String) -> Unit, onValueChanged: (String) -> Unit,
modifier: Modifier = Modifier imeAction: ImeAction
) { ) {
TextField( OutlinedTextField(
value = value, value = value,
singleLine = true,
leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) },
modifier = modifier,
onValueChange = onValueChanged, onValueChange = onValueChanged,
label = { Text(stringResource(label)) }, label = { Text(stringResource(label)) },
keyboardOptions = keyboardOptions leadingIcon = { Icon(painter = painterResource(id = leadingIcon), contentDescription = null) },
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = imeAction
),
singleLine = true,
modifier = Modifier.fillMaxWidth()
) )
} }
@Composable @Composable
fun RoundTheTipRow( fun UnitSwitchRow(isMetric: Boolean, onUnitChanged: (Boolean) -> Unit) {
roundUp: Boolean,
onRoundUpChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier
) {
Row( Row(
modifier = modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) { ) {
Text(text = stringResource(R.string.round_up_tip)) Text(text = stringResource(R.string.unit_system))
Switch( Row(verticalAlignment = Alignment.CenterVertically) {
modifier = Modifier Text("Imperial", style = MaterialTheme.typography.bodyMedium)
.fillMaxWidth() Switch(
.wrapContentWidth(Alignment.End), checked = isMetric,
checked = roundUp, onCheckedChange = onUnitChanged,
onCheckedChange = onRoundUpChanged modifier = Modifier.padding(horizontal = 8.dp)
) )
Text("Metric", style = MaterialTheme.typography.bodyMedium)
}
} }
} }
/** // --- FUNGSI LOGIKA (HELPER) ---
* Calculates the tip based on the user input and format the tip amount
* according to the local currency. private fun calculateBMI(height: Double, weight: Double, isMetric: Boolean): Double {
* Example would be "$10.00". if (height <= 0 || weight <= 0) return 0.0
*/
private fun calculateTip(amount: Double, tipPercent: Double = 15.0, roundUp: Boolean): String { return if (isMetric) {
var tip = tipPercent / 100 * amount val heightInMeters = height / 100
if (roundUp) { weight / (heightInMeters * heightInMeters)
tip = kotlin.math.ceil(tip) } else {
703 * weight / (height * height)
}
}
private fun bmiCategory(bmi: Double): String {
return when {
bmi == 0.0 -> "..."
bmi < 18.5 -> "Underweight"
bmi < 25.0 -> "Normal"
bmi < 30.0 -> "Overweight"
else -> "Obese"
} }
return NumberFormat.getCurrencyInstance().format(tip)
} }
@Preview(showBackground = true)
@Composable @Composable
fun TipTimeLayoutPreview() { private fun getBmiCategoryColor(category: String): Color {
TipTimeTheme { return when (category) {
TipTimeLayout() "Underweight" -> Color(0xFF8AB4F8) // Biru
"Normal" -> Color(0xFF5BB974) // Hijau
"Overweight" -> Color(0xFFFDD663) // Kuning
"Obese" -> Color(0xFFE57373) // Merah
else -> MaterialTheme.colorScheme.onSurface
}
}
// --- PREVIEW ---
@Preview(showBackground = true, name = "New BMI Calculator")
@Composable
fun BMICalculatorScreenPreview() {
TipTimeTheme {
BMICalculatorScreen()
} }
} }

View File

@ -0,0 +1,109 @@
package com.example.tiptime
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
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.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.draw.alpha
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
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
// Composable utama untuk Start Screen yang interaktif
@Composable
fun StartScreen(onNavigateToMain: () -> Unit) {
// State untuk memulai dan mengontrol animasi
var startAnimation by remember { mutableStateOf(false) }
val alphaAnim = animateFloatAsState(
targetValue = if (startAnimation) 1f else 0f,
animationSpec = tween(durationMillis = 2000), // Animasi logo & teks muncul selama 2 detik
label = "alpha_animation"
)
// LaunchedEffect sekarang hanya untuk memulai animasi saat layar pertama kali muncul
LaunchedEffect(key1 = true) {
startAnimation = true // Mulai animasi
}
// Tampilan UI untuk Start Screen
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
// --- Bagian Logo dan Judul (tetap sama) ---
Image(
painter = painterResource(id = R.drawable.ic_weight), // Menggunakan ikon timbangan
contentDescription = "App Logo",
modifier = Modifier
.size(120.dp)
.alpha(alphaAnim.value) // Terapkan animasi alpha
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = stringResource(id = R.string.app_name),
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.alpha(alphaAnim.value) // Terapkan animasi alpha
)
Spacer(modifier = Modifier.height(100.dp)) // Beri jarak lebih ke tombol
// --- Bagian Tombol Interaktif ---
// AnimatedVisibility akan membuat tombol muncul dengan animasi setelah logo tampil
AnimatedVisibility(
visible = startAnimation,
enter = slideInVertically(
initialOffsetY = { it }, // Muncul dari bawah
animationSpec = tween(durationMillis = 1000, delayMillis = 500) // Animasi setelah 0.5 detik
)
) {
Button(
// Saat tombol diklik, panggil fungsi untuk navigasi
onClick = onNavigateToMain,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 32.dp)
) {
Text(
text = "Mulai Hitung",
fontSize = 18.sp
)
}
}
}
}
// Preview khusus untuk StartScreen agar bisa dilihat di panel desain
@Preview(showBackground = true, name = "Start Screen Preview")
@Composable
fun StartScreenPreview() {
TipTimeTheme {
StartScreen(onNavigateToMain = {})
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,23 +0,0 @@
<!--
~ 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
~
~ https://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.
-->
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7.5,11C9.43,11 11,9.43 11,7.5S9.43,4 7.5,4S4,5.57 4,7.5S5.57,11 7.5,11zM7.5,6C8.33,6 9,6.67 9,7.5S8.33,9 7.5,9S6,8.33 6,7.5S6.67,6 7.5,6z"/>
<path android:fillColor="@android:color/white" android:pathData="M4.0025,18.5831l14.5875,-14.5875l1.4142,1.4142l-14.5875,14.5875z"/>
<path android:fillColor="@android:color/white" android:pathData="M16.5,13c-1.93,0 -3.5,1.57 -3.5,3.5s1.57,3.5 3.5,3.5s3.5,-1.57 3.5,-3.5S18.43,13 16.5,13zM16.5,18c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5S17.33,18 16.5,18z"/>
</vector>

View File

@ -15,10 +15,19 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<resources> <resources>
<string name="app_name">Tip Time</string> <string name="app_name">BMI Calculator</string>
<string name="calculate_tip">Calculate Tip</string> <string name="bmi_calculator">BMI Calculator</string>
<string name="bill_amount">Bill Amount</string> <string name="height_cm">Height (cm)</string>
<string name="how_was_the_service">Tip Percentage</string> <string name="height_in">Height (in)</string>
<string name="round_up_tip">Round up tip?</string> <string name="weight_kg">Weight (kg)</string>
<string name="tip_amount">Tip Amount: %s</string> <string name="weight_lbs">Weight (lbs)</string>
<string name="metric_units">Metric (kg, cm)</string>
<string name="imperial_units">Imperial (lbs, in)</string>
<string name="your_bmi">Your BMI: %s</string>
<string name="bmi_category">Category: %s</string>
<string name="your_bmi_is">Your BMI is</string>
<string name="unit_system">Unit System</string>
</resources> </resources>

View File

@ -14,14 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
buildscript {
extra.apply {
set("compose_compiler_version", "1.5.3")
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id("com.android.application") version "8.7.3" apply false id("com.android.application") version "8.13.0" apply false
id("com.android.library") version "8.7.3" apply false id("com.android.library") version "8.13.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.10" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.1.0" apply false
} }

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

3
gradlew vendored
View File

@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum