Tugas Minggu 10 PPB I
Nama : Tegar Ganang Satrio Priambodo
NRP : 5025201002
Kelas : PPB I
Latihan Activity dan Intent
Pada latihan ini, perlu untuk memahami lifecycle activity pada studi kasus aplikasi Dessert Clicker dimana ketika user berinteraksi dengan klik gambar kue, maka terjadi penambahan jumlah kue dan revenue yang diterima. Jumlah kue dan revenue tidak akan berkurang jika pengguna keluar dan masuk kembali ke aplikasi.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { | |
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<Dessert>, | |
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<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))) | |
} | |
} |
Komentar
Posting Komentar