Tugas 9: Aplikasi Dessert Clicker menggunakan Activity Lifecycle dan Intent
Aplikasi Dessert Clicker menggunakan Activity Lifecycle dan Intent
Langkah 1: Membuat Proyek Baru di Android Studio
- Buka Android Studio setelah instalasi selesai.
- Klik "Start a new Android Studio project".
- Pada layar pemilihan template, pilih "Empty Compose Activity" lalu klik Next.
- Masukkan nama aplikasi (misalnya, "My Dessert").
- Tentukan lokasi penyimpanan proyek di sistem Anda.
- Pilih Language sebagai Kotlin.
- Pastikan Use AndroidX artifacts dicentang.
- Klik Finish.
- Pada halaman "Select a minimum SDK", pilih API Level 24: Android 7.0 (Nougat) sebagai Minimum SDK.
- Android Studio akan mulai membangun proyek Anda. Tunggu hingga proses ini selesai.
Langkah 2: Mengedit File MainActivity.kt
- Setelah proyek selesai dibangun, buka file MainActivity.kt.
- Sesuaikan kode seperti berikut:
package com.example.dessertclicker import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.annotation.DrawableRes import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding 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.safeDrawing import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.material3.Scaffold import androidx.compose.material3.Icon import androidx.compose.material3.IconButton 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.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.core.content.ContextCompat import com.example.dessertclicker.data.Datasource import com.example.dessertclicker.model.Dessert import com.example.dessertclicker.ui.theme.DessertClickerTheme private const val TAG = "MainActivity" class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) Log.d(TAG, "onCreate Called") setContent { DessertClickerTheme { Surface( modifier = Modifier .fillMaxSize() .statusBarsPadding(), ) { DessertClickerApp(desserts = Datasource.dessertList) } } } } override fun onStart() { super.onStart() Log.d(TAG, "onStart Called") } override fun onResume() { super.onResume() Log.d(TAG, "onResume Called") } override fun onRestart() { super.onRestart() Log.d(TAG, "onRestart Called") } override fun onPause() { super.onPause() Log.d(TAG, "onPause Called") } override fun onStop() { super.onStop() Log.d(TAG, "onStop Called") } override fun onDestroy() { super.onDestroy() Log.d(TAG, "onDestroy Called") } } fun determineDessertToShow( desserts: List, dessertsSold: Int ): Dessert { var dessertToShow = desserts.first() for (dessert in desserts) { if (dessertsSold >= dessert.startProductionAmount) { dessertToShow = dessert } else { break } } return dessertToShow } private fun shareSoldDessertsInformation(intentContext: Context, dessertsSold: Int, revenue: Int) { val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra( Intent.EXTRA_TEXT, intentContext.getString(R.string.share_text, dessertsSold, revenue) ) type = "text/plain" } val shareIntent = Intent.createChooser(sendIntent, null) try { ContextCompat.startActivity(intentContext, shareIntent, null) } catch (e: ActivityNotFoundException) { Toast.makeText( intentContext, intentContext.getString(R.string.sharing_not_available), Toast.LENGTH_LONG ).show() } } @Composable private fun DessertClickerApp( desserts: List ) { var revenue by rememberSaveable { mutableStateOf(0) } var dessertsSold by rememberSaveable { mutableStateOf(0) } val currentDessertIndex by rememberSaveable { mutableStateOf(0) } var currentDessertPrice by rememberSaveable { mutableStateOf(desserts[currentDessertIndex].price) } var currentDessertImageId by rememberSaveable { mutableStateOf(desserts[currentDessertIndex].imageId) } Scaffold( topBar = { val intentContext = LocalContext.current val layoutDirection = LocalLayoutDirection.current DessertClickerAppBar( onShareButtonClicked = { shareSoldDessertsInformation( intentContext = intentContext, dessertsSold = dessertsSold, revenue = revenue ) }, modifier = Modifier .fillMaxWidth() .padding( start = WindowInsets.safeDrawing.asPaddingValues() .calculateStartPadding(layoutDirection), end = WindowInsets.safeDrawing.asPaddingValues() .calculateEndPadding(layoutDirection), ) .background(MaterialTheme.colorScheme.primary) ) } ) { contentPadding -> DessertClickerScreen( revenue = revenue, dessertsSold = dessertsSold, dessertImageId = currentDessertImageId, onDessertClicked = { revenue += currentDessertPrice dessertsSold++ val dessertToShow = determineDessertToShow(desserts, dessertsSold) currentDessertImageId = dessertToShow.imageId currentDessertPrice = dessertToShow.price }, modifier = Modifier.padding(contentPadding) ) } } @Composable private fun DessertClickerAppBar( onShareButtonClicked: () -> Unit, modifier: Modifier = Modifier ) { Row( modifier = modifier, horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { Text( text = stringResource(R.string.app_name), modifier = Modifier.padding(start = dimensionResource(R.dimen.padding_medium)), color = MaterialTheme.colorScheme.onPrimary, style = MaterialTheme.typography.titleLarge, ) IconButton( onClick = onShareButtonClicked, modifier = Modifier.padding(end = dimensionResource(R.dimen.padding_medium)), ) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.share), tint = MaterialTheme.colorScheme.onPrimary ) } } } @Composable fun DessertClickerScreen( revenue: Int, dessertsSold: Int, @DrawableRes dessertImageId: Int, onDessertClicked: () -> Unit, modifier: Modifier = Modifier ) { Box(modifier = modifier) { Image( painter = painterResource(R.drawable.bakery_back), contentDescription = null, contentScale = ContentScale.Crop ) Column { Box( modifier = Modifier .weight(1f) .fillMaxWidth(), ) { Image( painter = painterResource(dessertImageId), contentDescription = null, modifier = Modifier .width(dimensionResource(R.dimen.image_size)) .height(dimensionResource(R.dimen.image_size)) .align(Alignment.Center) .clickable { onDessertClicked() }, contentScale = ContentScale.Crop, ) } TransactionInfo( revenue = revenue, dessertsSold = dessertsSold, modifier = Modifier.background(MaterialTheme.colorScheme.secondaryContainer) ) } } } @Composable private fun TransactionInfo( revenue: Int, dessertsSold: Int, modifier: Modifier = Modifier ) { Column(modifier = modifier) { DessertsSoldInfo( dessertsSold = dessertsSold, modifier = Modifier .fillMaxWidth() .padding(dimensionResource(R.dimen.padding_medium)) ) RevenueInfo( revenue = revenue, modifier = Modifier .fillMaxWidth() .padding(dimensionResource(R.dimen.padding_medium)) ) } } @Composable private fun RevenueInfo(revenue: Int, modifier: Modifier = Modifier) { Row( modifier = modifier, horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(R.string.total_revenue), style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.onSecondaryContainer ) Text( text = "${revenue}", textAlign = TextAlign.Right, style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.onSecondaryContainer ) } } @Composable private fun DessertsSoldInfo(dessertsSold: Int, modifier: Modifier = Modifier) { Row( modifier = modifier, horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(R.string.dessert_sold), style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onSecondaryContainer ) Text( text = dessertsSold.toString(), style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onSecondaryContainer ) } } @Preview @Composable fun MyDessertClickerAppPreview() { DessertClickerTheme { DessertClickerApp(listOf(Dessert(R.drawable.cupcake, 5, 0))) } }
Langkah 3: Menjalankan Aplikasi
- Klik "Run" (ikon hijau di toolbar) untuk menjalankan aplikasi.
- Pilih Emulator yang sudah Anda siapkan atau sambungkan perangkat fisik Android Anda.
- Android Studio akan membangun dan menjalankan aplikasi.

.jpeg)
.jpeg)
Comments
Post a Comment