Latihan Materi Kontrol Input - Aplikasi Tip Calculator

Nama     : Helsa Nesta Dhaifullah
NRP       : 5025201005
Kelas      : PPB I - 2024 

Tentang Tip Calculator

Aplikasi tip calculator merupakan aplikasi untuk menghitung dan menampilkan nominal tip yang disarankan berdasarkan input "Jumlah Tagihan" dan "Presentase Tip" dari pengguna. Awalnya presentase tip di hardcode 15%. Namun dalam pengembangannya, kita akan mengubahnya menjadi input pengguna. Berikut adalah tampilan hasil akhir dari aplikasi tip calculator.




Untuk mendapatkan kode awal/starter dari aplikasi ini, kita dapat men-download di tautan Github berikut:
https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator/archive/refs/heads/starter.zip

Atau dapat membuat clone repositori GitHub untuk kode tersebut:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git
$ cd basic-android-kotlin-compose-training-tip-calculator
$ git checkout starter

Menggunakan State dalam Compose

State di aplikasi adalah nilai yang dapat berubah dari waktu ke waktu. Di aplikasi ini, state adalah jumlah tagihan.
  1. Di awal fungsi EditNumberField(), gunakan kata kunci val untuk menambahkan variabel amountInput, tetapkan ke nilai "0":
    val amountInput = "0"
  2. Setel parameter bernama value ke nilai amountInput:
    TextField(
       value = amountInput,
       onValueChange = {},
    )
  3. Jalankan aplikasi di emulator, coba masukkan nilai lain. Status hardcode tetap tidak berubah karena composable TextField tidak memperbarui sendiri. Composable ini diperbarui saat parameter value berubah, yang disetel ke properti amountInput.

Komposisi

Kitamenggunakan jenis State dan MutableState di Compose agar status di aplikasi kita dapat diamati, atau dilacak, oleh Compose. Jenis State tidak dapat diubah, sehingga kita hanya dapat membaca nilai di dalamnya, sedangkan jenis MutableState dapat berubah. Nilai yang ditampilkan oleh fungsi mutableStateOf():
  • Mempertahankan state, yang merupakan jumlah tagihan.
  • Dapat diubah, sehingga nilai dapat diubah.
  • Dapat diamati, jadi Compose mengamati setiap perubahan pada nilai dan memicu rekomposisi untuk mengupdate UI.
Tambahkan state biaya layanan:
  1. Dalam fungsi EditNumberField(), ubah kata kunci val sebelum variabel state amountInput menjadi kata kunci var. Hal ini akan membuat amountInput dapat diubah.
    var amountInput = "0"
  2. Gunakan jenis MutableState<String>, bukan variabel String hardcode, sehingga Compose tahu cara melacak status amountInput, lalu meneruskan string "0" yang merupakan nilai default awal untuk variabel status amountInput:
    import androidx.compose.runtime.MutableState
    import androidx.compose.runtime.mutableStateOf
    
    var amountInput: MutableState<String> = mutableStateOf("0")
  3. Dalam fungsi composable TextField, gunakan properti amountInput.value:
    TextField(
       value = amountInput.value,
       onValueChange = {},
       modifier = modifier
    )
  4. Dalam ekspresi lambda parameter bernama onValueChange, setel properti amountInput.value ke variabel it:
    @Composable
    fun EditNumberField(modifier: Modifier = Modifier) {
       var amountInput = mutableStateOf("0")
       TextField(
           value = amountInput.value,
           onValueChange = { amountInput.value = it },
           modifier = modifier
       )
    }
  5. Jalankan aplikasi dan masukkan teks di kotak teks. Kotak teks masih menampilkan nilai 0 seperti yang dapat Anda lihat pada gambar ini:


Fungsi Remember untuk Menyimpan State

Fungsi composable dapat menyimpan objek di seluruh rekomposisi dengan remember. Nilai yang dihitung oleh fungsi remember disimpan dalam Komposisi selama komposisi awal dan nilai yang disimpan ditampilkan selama rekomposisi. Biasanya fungsi remember dan mutableStateOf digunakan bersama dalam fungsi composable agar status dan pembaruannya ditampilkan dengan benar di UI.
  1. Dalam fungsi EditNumberField(), lakukan inisialisasi variabel amountInput dengan delegasi properti Kotlin by remember, dengan mengapit panggilan ke fungsi mutableStateOf() dengan remember. Isi dengan string kosong.
    import androidx.compose.runtime.remember
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.setValue
    
    @Composable
    fun EditNumberField(modifier: Modifier = Modifier) {
       var amountInput by remember { mutableStateOf("") }
       TextField(
           value = amountInput,
           onValueChange = { amountInput = it },
           modifier = modifier
       )
    }
  2. Jalankan aplikasi dan masukkan teks di kotak teks. Kita akan melihat teks yang kita ketik sekarang.

Ubah Tampilan UI

Ubah fungsi EditNumberField() untuk menambahkan label ke kolom teks:
  1. Dalam fungsi composable TextField() dari fungsi EditNumberField(), tambahkan parameter bernama label yang disetel ke ekspresi lambda. Di dalamnya masukkan Text() yang menerima stringResource(R.string.bill_amount).
  2. Tambahkan parameter bernama singleLine yang disetel ke nilai true
  3. Setel jenis keyboard ke keyboard angka untuk memasukkan angka. Tambahkan parameter keyboardOptions yang disetel ke KeyboardOptions(). Teruskan fungsi KeyboardOptions dengan parameter bernama keyboardType yang disetel ke KeyboardType.Number:
Fungsi EditNumberField() yang telah selesai akan terlihat seperti cuplikan kode ini:
@Composable
fun EditNumberField(modifier: Modifier = Modifier) {
    var amountInput by remember { mutableStateOf("") }
    TextField(
        value = amountInput,
        onValueChange = { amountInput = it },
        singleLine = true,
        label = { Text(stringResource(R.string.bill_amount)) },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
        modifier = modifier
    )
}

Menampilkan Jumlah Tip

Di bagian ini, kita akan menerapkan fungsi utama aplikasi, yaitu kemampuan untuk menghitung dan menampilkan jumlah tip. Dalam file MainActivity.kt, fungsi private calculateTip() diberikan dalam kode awal. Kita akan menggunakan fungsi ini untuk menghitung jumlah tip:
  1. Dalam fungsi composable EditNumberField(), buat variabel baru bernama amount setelah definisi amountInput. Panggil fungsi toDoubleOrNull pada variabel amountInput, untuk mengonversi String menjadi Double:
  2. Di akhir pernyataan, tambahkan operator Elvis ?: yang menampilkan nilai 0.0 jika amountInput adalah null:
  3. Setelah variabel amount, buat variabel val lain bernama tip. Lakukan inisialisasi dengan calculateTip(), dengan meneruskan parameter amount.
Fungsi EditNumberField() akan terlihat seperti cuplikan kode ini:
@Composable
fun EditNumberField(modifier: Modifier = Modifier) {
   var amountInput by remember { mutableStateOf("") }

   val amount = amountInput.toDoubleOrNull() ?: 0.0
   val tip = calculateTip(amount)

   TextField(
       value = amountInput,
       onValueChange = { amountInput = it },
       label = { Text(stringResource(R.string.bill_amount)) },
       modifier = Modifier.fillMaxWidth(),
       singleLine = true,
       keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
   )
}
Kita telah menulis fungsi untuk menghitung jumlah tip, langkah selanjutnya adalah menampilkan jumlah tip yang dihitung:
  1. Dalam fungsi TipTimeLayout() di akhir blok Column(), perhatikan composable teks yang menampilkan $0.00. Anda akan memperbarui nilai ini ke jumlah tip yang dihitung.
    @Composable
    fun TipTimeLayout() {
        Column(
            modifier = Modifier
                .statusBarsPadding()
                .padding(horizontal = 40.dp)
                .verticalScroll(rememberScrollState())
                .safeDrawingPadding(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            // ...
            Text(
                text = stringResource(R.string.tip_amount, "$0.00"),
                style = MaterialTheme.typography.displaySmall
            )
            // ...
        }
    }

Pengangkatan State

  1. Perbarui definisi fungsi EditNumberField(), untuk mengangkat state dengan menambahkan parameter value dan onValueChange.
  2. Dalam fungsi EditNumberField(), perbarui fungsi composable TextField() untuk menggunakan parameter yang diteruskan.
  3. Mengangkat state, memindahkan state yang diingat dari fungsi EditNumberField() ke fungsi TipTimeLayout().
  4. Sekarang teruskan ke EditNumberField(). Dalam fungsi TipTimeLayout(), perbarui panggilan fungsi EditNumberField() untuk menggunakan state yang diangkat.
  5. Dalam fungsi, TipTimeLayout(), gunakan properti tip untuk menampilkan jumlah tip. Perbarui parameter text composable Text untuk menggunakan variabel tip sebagai parameter.
Fungsi TipTimeLayout() dan EditNumberField() yang selesai akan terlihat seperti cuplikan kode ini:
@Composable
fun TipTimeLayout() {
   var amountInput by remember { mutableStateOf("") }
   val amount = amountInput.toDoubleOrNull() ?: 0.0
   val tip = calculateTip(amount)

   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(
           value = amountInput,
           onValueChange = { amountInput = it },
           modifier = Modifier
               .padding(bottom = 32.dp)
               .fillMaxWidth()
       )
       Text(
           text = stringResource(R.string.tip_amount, tip),
           style = MaterialTheme.typography.displaySmall
       )
       Spacer(modifier = Modifier.height(150.dp))
   }
}

@Composable
fun EditNumberField(
   value: String,
   onValueChange: (String) -> Unit,
   modifier: Modifier = Modifier
) {
   TextField(
       value = value,
       onValueChange = onValueChange,
       singleLine = true,
       label = { Text(stringResource(R.string.bill_amount)) },
       keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
       modifier = modifier
   )
}

Kode Solusi

Untuk men-download kode codelab yang sudah selesai, kita dapat menggunakan perintah git berikut:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git
$ cd basic-android-kotlin-compose-training-tip-calculator
$ git checkout state
Atau, kita dapat men-download repositori sebagai file zip, mengekstraknya, dan membukanya di Android Studio.

Jika Anda ingin melihat kode solusi, lihat di GitHub.

Komentar

Postingan Populer