PPB I - Tugas Pert 10
Tugas Pert 10
Nama : Rachel Anggieuli AP
NRP : 5025201263
Tahun : 2023/2024
Kelas
: PPB I
Activity and Intent
Pada tugas kali ini, ditugaskan untuk membuat Aplikasi Dessert Clicker pada android studio dengan menggunakan Activity dan Intent. Activity digunakan untuk mengelola pergantian layar dan Intent digunakan untuk menghubungkan antara activity satu dengan activity lain.
Link TutorialLink Tutorial-Github
Dokumentasi Aplikasi
Langkah Pengerjaan
Unduh file Zip Starter dari tautan yang diberikan dan buka file tersebut di Android Studio.
MainActivity.kt
<> 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 // Tag for logging private const val TAG = "MainActivity" class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) Log.d(TAG, "onCreate Called") setContent { DessertClickerTheme { // A surface container using the 'background' color from the theme 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") } } /** * Determine which dessert to show. */ fun determineDessertToShow( desserts: List<Dessert<, dessertsSold: Int ): Dessert { var dessertToShow = desserts.first() for (dessert in desserts) { if (dessertsSold >= dessert.startProductionAmount) { dessertToShow = dessert } else { // The list of desserts is sorted by startProductionAmount. As you sell more desserts, // you'll start producing more expensive desserts as determined by startProductionAmount // We know to break as soon as we see a dessert who's "startProductionAmount" is greater // than the amount sold. break } } return dessertToShow } /** * Share desserts sold information using ACTION_SEND intent */ 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<Dessert< ) { 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 = { // Update the revenue revenue += currentDessertPrice dessertsSold++ // Show the next dessert 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))) } } <>
Comments
Post a Comment