Menghitung tip kustom

1. Sebelum memulai

Dalam codelab ini, Anda akan menggunakan kode solusi dari codelab Pengantar status di Compose guna membuat kalkulator tip interaktif yang dapat secara otomatis menghitung dan membulatkan jumlah tip saat Anda memasukkan jumlah tagihan dan persentase tip. Anda dapat melihat aplikasi final dalam gambar ini:

24370de6d667a700.png

Prasyarat

  • Status Penggunaan di codelab Jetpack Compose
  • Kemampuan untuk menambahkan composable Text dan TextField ke aplikasi.
  • Pengetahuan tentang fungsi remember, status, pengangkatan status, dan perbedaan antara fungsi composable stateful dan stateless

Yang akan Anda pelajari

  • Cara menambahkan tombol tindakan ke keyboard virtual.
  • Cara menyiapkan tindakan keyboard.
  • Pengertian composable Switch dan cara menggunakannya.
  • Pengertian Layout Inspector.

Yang akan Anda bangun

  • Aplikasi Tip Time yang menghitung jumlah tip berdasarkan biaya layanan dan persentase tip yang dimasukkan pengguna.

Yang akan Anda butuhkan

  • Android Studio
  • Kode solusi dari status Penggunaan di codelab Jetpack Compose

2. Ringkasan aplikasi awal

Codelab ini dimulai dengan Aplikasi Tip Time dari codelab sebelumnya, yang menyediakan antarmuka pengguna yang diperlukan untuk menghitung tip dengan persentase tip tetap. Pengguna dapat memasukkan biaya layanan ke dalam kotak teks Biaya Layanan yang tersedia. Aplikasi ini akan menghitung dan menampilkan jumlah tip dalam composable Text.

Mendapatkan kode awal

Untuk memulai, download kode awal:

Atau, Anda 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 state

Anda dapat menjelajahi kode di repositori GitHub Tip Calculator.

Menjalankan Aplikasi Tip Time

  1. Buka project Tip Time di Android Studio dan jalankan aplikasi di emulator atau perangkat.
  2. Masukkan biaya layanan. Aplikasi akan secara otomatis menghitung dan menampilkan jumlah tip.

761df483de663721.png

Dalam penerapan saat ini, persentase tip di-hardcode menjadi 15%. Dalam codelab ini, Anda akan memperluas fitur ini menggunakan kolom teks yang memungkinkan aplikasi menghitung persentase tip kustom dan membulatkan jumlah tip.

Menambahkan resource string yang diperlukan

  1. Di tab Project, klik res > values > strings.xml.
  2. Di antara tag <resources> file strings.xml, tambahkan resource string berikut:
<string name="how_was_the_service">Tip (%)</string>
<string name="round_up_tip">Round up tip?</string>

File strings.xml akan terlihat seperti cuplikan kode ini, yang menyertakan string dari codelab sebelumnya:

strings.xml

<resources>
   <string name="app_name">TipTime</string>
   <string name="calculate_tip">Calculate Tip</string>
   <string name="cost_of_service">Cost of Service</string>
   <string name="how_was_the_service">Tip (%)</string>
   <string name="round_up_tip">Round up tip?</string>
   <string name="tip_amount">Tip Amount: %s</string>
</resources>
  1. Ubah string Cost Of Service menjadi string Bill Amount. Di beberapa negara, layanan berarti tip, sehingga perubahan diharapkan dapat mencegah kebingungan akan istilah tersebut.
  2. Di string Cost of Service, klik kanan atribut name cost_of_service, lalu pilih Refactor > Rename. Dialog Rename akan terbuka.

a2f301b95a8c0e3f.png

  1. Di kotak dialog Rename, ganti cost_of _service dengan bill_amount lalu klik Refactor. Tindakan ini akan memperbarui semua kemunculan resource string cost_of_service dalam project, sehingga Anda tidak perlu mengubah kode Compose secara manual.

f525a371c2851d08.png

  1. Dalam file​​ strings.xml, ubah nilai string menjadi Bill Amount dari Cost of Service:
<string name="bill_amount">Bill Amount</string>
  1. Buka file MainActivity.kt, lalu jalankan aplikasi. Label diperbarui di kotak teks seperti yang dapat Anda lihat pada gambar ini:

kolom teks menampilkan jumlah tagihan, bukan biaya layanan

3. Menambahkan kolom teks persentase tip

Pelanggan mungkin ingin memberikan lebih banyak atau lebih sedikit berdasarkan kualitas layanan yang diberikan dan berbagai alasan lainnya. Untuk mengakomodasi hal ini, aplikasi harus memungkinkan pengguna menghitung tip kustom. Di bagian ini, Anda akan menambahkan kolom teks bagi pengguna untuk memasukkan persentase tip kustom seperti yang dapat Anda lihat pada gambar ini:

47b5e8543e5eb754.png

Anda sudah memiliki composable kolom teks Bill Amount di aplikasi, dan ini merupakan fungsi composable EditNumberField() stateless. Di codelab sebelumnya, Anda telah mengangkat status amountInput dari composable EditNumberField() ke fungsi TipTimeScreen() sehingga composable EditNumberField() menjadi stateless.

Untuk menambahkan kolom teks, Anda dapat menggunakan kembali composable EditNumberField() yang sama, tetapi dengan label yang berbeda. Untuk melakukan perubahan ini, Anda harus meneruskan label sebagai parameter, bukan melakukan hardcode pada fungsi composable EditNumberField().

Buat fungsi composable EditNumberField() bisa digunakan kembali:

  1. Dalam file MainActivity.kt di parameter fungsi composable EditNumberField(), tambahkan resource string label dari jenis Int:
@Composable
fun EditNumberField(
   label: Int,
   value: String,
   onValueChange: (String) -> Unit
) 
  1. Tambahkan argumen modifier dari jenis Modifier ke fungsi composable EditNumberField():
@Composable
fun EditNumberField(
   label: Int,
   value: String,
   onValueChange: (String) -> Unit,
   modifier: Modifier = Modifier
) 
  1. Dalam isi fungsi, ganti ID resource string hardcode dengan parameter label:
@Composable
fun EditNumberField(
   //...
) {
   TextField(
       //...
       label = { Text(stringResource(label)) },
       //...
   )
}
  1. Untuk menunjukkan bahwa parameter label diharapkan akan menjadi referensi resource string, anotasikan parameter fungsi dengan anotasi @StringRes:
@Composable
fun EditNumberField(
   @StringRes label: Int,
   value: String,
   onValueChange: (String) -> Unit,
   modifier: Modifier = Modifier
) 
  1. Impor hal berikut:
import androidx.annotation.StringRes
  1. Pada composable TextField fungsi EditNumberField(), teruskan parameter label ke fungsi stringResource().
@Composable
fun EditNumberField(
   @StringRes label: Int,
   value: String,
   onValueChange: (String) -> Unit,
   modifier: Modifier = Modifier
) {
   TextField(
       //...
       label = { Text(stringResource(label)) },
       //...
   )
} 
  1. Pada panggilan fungsi EditNumberField() fungsi TipTimeScreen(), tetapkan parameter label ke resource string R.string.bill_amount:
EditNumberField(
   label = R.string.bill_amount,
   value = amountInput,
   onValueChange = { amountInput = it }
)
  1. Di panel Design, klik 2d40b921003ab5eb.png Build & Refresh. UI aplikasi akan terlihat seperti gambar ini:

a84cd50c50235a9f.png

  1. Pada fungsi TipTimeScreen() setelah panggilan fungsi EditNumberField(), tambahkan kolom teks lain untuk persentase tip kustom. Lakukan panggilan ke fungsi composable EditNumberField() dengan parameter ini:
EditNumberField(
   label = R.string.how_was_the_service,
   value = "",
   onValueChange = { }
)

Tindakan ini akan menambahkan kotak teks lain untuk persentase tip kustom.

  1. Di panel Design, klik 2d40b921003ab5eb.png Build & Refresh. Pratinjau aplikasi kini menampilkan kolom teks Tip (%) seperti yang dapat Anda lihat dalam gambar ini:

9d2c01d577d077ae.png

  1. Di bagian atas fungsi TipTimeScreen(), tambahkan properti var yang disebut tipInput untuk variabel status kolom teks yang ditambahkan. Gunakan mutableStateOf("") untuk melakukan inisialisasi pada variabel dan mengapit panggilan dengan fungsi remember:
var tipInput by remember { mutableStateOf("") }
  1. Pada panggilan fungsi EditNumberField() baru, setel parameter bernama value menjadi variabel tipInput, lalu update variabel tipInput dalam ekspresi lambda onValueChange:
EditNumberField(
   label = R.string.how_was_the_service,
   value = tipInput,
   onValueChange = { tipInput = it }
)
  1. Pada fungsi TipTimeScreen() setelah definisi variabel tipInput, tentukan variabel val bernama tipPercent yang mengubah variabel tipInput menjadi jenis Double, gunakan operator elvis, lalu tampilkan 0.0 jika nilainya null:
val tipPercent = tipInput.toDoubleOrNull() ?: 0.0
  1. Pada fungsi TipTimeScreen(), update panggilan fungsi calculateTip(), teruskan variabel tipPercent sebagai parameter kedua:
val tip = calculateTip(amount, tipPercent)

Kode untuk fungsi TipTimeScreen() kini akan terlihat seperti cuplikan kode ini:

@Composable
fun TipTimeScreen() {
   var amountInput by remember { mutableStateOf("") }
   var tipInput by remember { mutableStateOf("") }

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

   Column(
       modifier = Modifier.padding(32.dp),
       verticalArrangement = Arrangement.spacedBy(8.dp)
   ) {
       Text(
           text = stringResource(R.string.calculate_tip),
           fontSize = 24.sp,
           modifier = Modifier.align(Alignment.CenterHorizontally)
       )
       Spacer(Modifier.height(16.dp))
       EditNumberField(
           label = R.string.bill_amount,
           value = amountInput,
           onValueChange = { amountInput = it }
       )
       EditNumberField(
           label = R.string.how_was_the_service,
           value = tipInput,
           onValueChange = { tipInput = it }
       )
       Spacer(Modifier.height(24.dp))
       Text(
           text = stringResource(R.string.tip_amount, tip),
           modifier = Modifier.align(Alignment.CenterHorizontally),
           fontSize = 20.sp,
           fontWeight = FontWeight.Bold
       )
   }
}
  1. Jalankan aplikasi di emulator atau perangkat, lalu masukkan jumlah tagihan dan persentase tip. Apakah aplikasi menghitung jumlah tip dengan benar?

bdc482b015472300.png

4. Menyetel tombol tindakan

Pada codelab sebelumnya, Anda telah mempelajari cara menggunakan class KeyboardOptions untuk menetapkan jenis keyboard. Di bagian ini, Anda akan mempelajari cara menyetel tombol tindakan keyboard dengan KeyboardOptions yang sama. Tombol tindakan keyboard adalah tombol di bagian akhir keyboard. Anda dapat melihat beberapa contoh dalam tabel ini:

Properti

Tombol tindakan di keyboard

ImeAction.Search digunakan saat pengguna ingin menjalankan penelusuran.

ImeAction.Send digunakan saat pengguna ingin mengirim teks di kolom input.

ImeAction.Go digunakan saat pengguna ingin membuka target teks di input.

Dalam tugas ini, Anda menyetel dua tombol tindakan yang berbeda untuk kotak teks:

  • Tombol tindakan Next untuk kotak teks Bill Amount yang menunjukkan bahwa pengguna telah selesai memasukkan input saat ini dan ingin pindah ke kotak teks berikutnya.
  • Tombol tindakan Done untuk kotak teks Tip % yang menunjukkan bahwa pengguna selesai memberikan input.

Anda dapat melihat contoh keyboard dengan tombol tindakan ini dalam gambar berikut:

Menambahkan opsi keyboard:

  1. Pada panggilan fungsi TextField() dari fungsi EditNumberField(), teruskan argumen bernama imeAction pada konstruktor KeyboardOptions ke nilai ImeAction.Next. Gunakan fungsi KeyboardOptions.Default.copy untuk menggunakan opsi default lain seperti penggunaan huruf besar dan koreksi otomatis.
@Composable
fun EditNumberField(
   //...
) {
   TextField(
       //...
       keyboardOptions = KeyboardOptions.Default.copy(
           keyboardType = KeyboardType.Number,
           imeAction = ImeAction.Next
       )
   )
}
  1. Menjalankan aplikasi di emulator atau perangkat. Sekarang keyboard dapat menampilkan tombol tindakan Next seperti yang dapat Anda lihat dalam gambar ini:

Namun, Anda ingin dua tombol tindakan yang berbeda untuk kolom teks. Anda akan segera memperbaiki masalah ini.

  1. Periksa fungsi EditNumberField(). Parameter keyboardOptions dalam fungsi TextField() di-hardcode. Untuk membuat tombol tindakan yang berbeda untuk kolom teks, Anda harus meneruskan objek KeyboardOptions sebagai argumen, yang akan Anda lakukan di langkah berikutnya.
// No need to copy, just examine the code.
fun EditNumberField(
   @StringRes label: Int,
   value: String,
   onValueChange: (String) -> Unit
) {
   TextField(
       //...
       keyboardOptions = KeyboardOptions.Default.copy(
          keyboardType = KeyboardType.Number,
          imeAction = ImeAction.Next
       )
   )
}
  1. Pada definisi fungsi EditNumberField(), tambahkan parameter keyboardOptions dari jenis KeyboardOptions. Dalam isi fungsi, tetapkan ke parameter bernama keyboardOptions dari fungsi TextField():
@Composable
fun EditNumberField(
   @StringRes label: Int,
   keyboardOptions: KeyboardOptions,
   value: String,
   onValueChange: (String) -> Unit
){
   TextField(
       //...
       keyboardOptions = keyboardOptions
   )
}
  1. Pada fungsi TipTimeScreen(), update panggilan fungsi EditNumberField() pertama, teruskan parameter bernama keyboardOptions untuk kolom teks Bill Amount.
EditNumberField(
   label = R.string.bill_amount,
   keyboardOptions = KeyboardOptions(
       keyboardType = KeyboardType.Number,
       imeAction = ImeAction.Next
   ),
   value = amountInput,
   onValueChange = { amountInput = it }
)
  1. Pada panggilan fungsi EditNumberField() kedua, ubah imeAction kolom teks Tip % menjadi ImeAction.Done. Fungsi Anda akan terlihat seperti cuplikan kode ini:
EditNumberField(
   label = R.string.how_was_the_service,
   keyboardOptions = KeyboardOptions(
       keyboardType = KeyboardType.Number,
       imeAction = ImeAction.Done
   ),
   value = tipInput,
   onValueChange = { tipInput = it }
)
  1. Jalankan aplikasi. Kode ini akan menampilkan tombol tindakan Next dan Done seperti yang dapat Anda lihat dalam gambar berikut:

  1. Masukkan jumlah tagihan apa pun, lalu klik tombol tindakan Next, lalu masukkan persentase tip dan klik tombol tindakan Done. Tidak ada yang terjadi karena Anda belum menambahkan fungsi apa pun ke tombol. Anda dapat melakukannya di bagian berikutnya.

5. Menetapkan tindakan keyboard

Di bagian ini, Anda akan menerapkan fungsi untuk memindahkan fokus ke kolom teks berikutnya dan menutup keyboard untuk meningkatkan pengalaman pengguna dengan class KeyboardActions, yang memungkinkan developer menentukan tindakan yang dipicu dalam merespons tindakan IME (Editor Metode Input) pengguna di keyboard virtual. Contoh tindakan IME adalah saat pengguna mengklik tombol tindakan Next atau Done.

Anda menerapkan hal berikut:

  • Pada tindakan Next: Pindahkan fokus ke kolom teks berikutnya (kotak teks Tip %).
  • Pada tindakan Done: Tutup keyboard virtual.
  1. Dalam fungsi EditNumberField(), tambahkan variabel val bernama focusManager dan tetapkan nilai properti LocalFocusManager.current:
val focusManager = LocalFocusManager.current

Antarmuka LocalFocusManager digunakan untuk mengontrol fokus di Compose. Anda menggunakan variabel ini untuk memindahkan fokus ke, dan menghapus fokus dari, kotak teks.

  1. Impor import androidx.compose.ui.platform.LocalFocusManager.
  2. Di tanda tangan fungsi EditNumberField(), tambahkan parameter keyboardActions lain dari jenis KeyboardActions:
@Composable
fun EditNumberField(
   @StringRes label: Int,
   keyboardOptions: KeyboardOptions,
   keyboardActions: KeyboardActions,
   value: String,
   onValueChange: (String) -> Unit
) {
   //...
}
  1. Pada isi fungsi EditNumberField(), update panggilan fungsi TextField(), tetapkan parameter keyboardActions ke parameter keyboardActions yang diteruskan.
@Composable
fun EditNumberField(
   //...
) {
   TextField(
       //...
       keyboardActions = keyboardActions
   )
}

Sekarang Anda dapat menyesuaikan kolom teks dengan fungsi yang berbeda untuk setiap tombol tindakan.

  1. Pada panggilan fungsi TipTimeScreen(), update panggilan fungsi EditNumberField() pertama untuk menyertakan parameter bernama keyboardActions sebagai argumen baru. Tetapkan nilai padanya, KeyboardActions( onNext = { } ):
// Bill amount text field
EditNumberField(
   //...
   keyboardActions = KeyboardActions(
       onNext = { }
   ),
   //...
)

Ekspresi lambda parameter bernama onNext berjalan saat pengguna menekan tombol tindakan Next di keyboard.

  1. Tentukan lambda, minta FocusManager untuk memindahkan fokus ke bawah ke composable berikutnya, Tip %. Dalam ekspresi lambda, panggil fungsi moveFocus() pada objek focusManager, lalu teruskan argumen FocusDirection.Down:
// Bill amount text field
EditNumberField(
   label = R.string.bill_amount,
   keyboardOptions = KeyboardOptions(
       keyboardType = KeyboardType.Number,
       imeAction = ImeAction.Next
   ),
   keyboardActions = KeyboardActions(
       onNext = { focusManager.moveFocus(FocusDirection.Down) }
   ),
   value = amountInput,
   onValueChange = { amountInput = it }
)

Fungsi moveFocus() memindahkan fokus ke arah yang ditentukan, yang dalam hal ini berada di kolom teks Tip %.

  1. Impor hal berikut:
import androidx.compose.ui.focus.FocusDirection
  1. Tambahkan implementasi serupa ke kolom teks Tip %. Perbedaannya adalah Anda perlu menentukan parameter bernama onDone, bukan onNext.
// Tip% text field
EditNumberField(
   //...
   keyboardActions = KeyboardActions(
       onDone = { }
   ),
   //...
)
  1. Setelah pengguna memasukkan tip kustom, tindakan Done pada keyboard akan menghapus fokus, yang kemudian akan menutup keyboard. Menentukan lambda, meminta FocusManager untuk menghapus fokus. Dalam ekspresi lambda, panggil fungsi clearFocus() pada objek focusManager:
EditNumberField(
   label = R.string.how_was_the_service,
   keyboardOptions = KeyboardOptions(
       keyboardType = KeyboardType.Number,
       imeAction = ImeAction.Done
   ),
   keyboardActions = KeyboardActions(
       onDone = { focusManager.clearFocus() }),
   value = tipInput,
   onValueChange = { tipInput = it }
)

Fungsi clearFocus() menghapus fokus dari komponen yang sedang menjadi fokus.

  1. Jalankan aplikasi. Tindakan keyboard kini mengubah komponen yang sedang menjadi fokus, seperti yang dapat Anda lihat dalam GIF ini:

3164e7a2f39a2d7b.gif

6. Menambahkan tombol

Tombol akan mengaktifkan atau menonaktifkan status suatu item. Ada dua status dalam tombol yang memungkinkan pengguna memilih antara dua opsi. Tombol terdiri dari thumb dan track seperti yang dapat Anda lihat dalam gambar ini:

1. Thumb
2. Track

Tombol adalah kontrol pemilihan yang dapat digunakan untuk memasukkan keputusan atau mendeklarasikan preferensi, seperti setelan yang dapat Anda lihat dalam gambar ini:

a90c4e22e48b30e0.png

Pengguna dapat menarik thumb bolak-balik untuk memilih opsi pilihan, atau cukup mengetuk tombol untuk beralih. Anda dapat melihat contoh lain tombol dalam GIF ini dengan setelan Visual options dialihkan ke Dark mode:

91b7bd7a6e02e5ff.gif

Untuk mempelajari tombol lebih lanjut, lihat dokumentasi Tombol.

Anda menggunakan composable Switch sehingga pengguna dapat memilih untuk membulatkan tip ke bilangan bulat terdekat, seperti yang Anda lihat dalam gambar ini, atau tidak:

cf89a61484296bab.png

Tambahkan baris untuk composable Text dan Switch:

  1. Setelah fungsi EditNumberField(), tambahkan fungsi composable RoundTheTipRow(), lalu teruskan Modifier default sebagai argumen yang serupa dengan fungsi EditNumberField():
@Composable
fun RoundTheTipRow(modifier: Modifier = Modifier) {
}
  1. Terapkan fungsi RoundTheTipRow(), tambahkan composable tata letak Row dengan modifier berikut untuk menetapkan lebar elemen turunan ke maksimum di layar, memosisikan perataan di tengah, dan memastikan ukuran 48 dp:
Row(
   modifier = Modifier
       .fillMaxWidth()
       .size(48.dp),
   verticalAlignment = Alignment.CenterVertically
) {
}
  1. Impor hal berikut:
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Size
  1. Di blok lambda composable tata letak Row, tambahkan composable Text yang menggunakan resource string R.string.round_up_tip untuk menampilkan string Round up tip?:
Text(text = stringResource(R.string.round_up_tip))
  1. Setelah composable Text, tambahkan composable Switch, dan teruskan parameter bernama checked, tetapkan ke roundUp dan parameter bernama onCheckedChange menetapkannya ke onRoundUpChanged.
Switch(
    checked = roundUp,
    onCheckedChange = onRoundUpChanged,
)

Tabel ini berisi informasi tentang parameter tersebut, yang merupakan parameter yang sama, yang Anda tentukan untuk fungsi RoundTheTipRow():

Parameter

Deskripsi

checked

Apakah tombol diperiksa. Ini adalah status composable Switch.

onCheckedChange

Callback yang akan dipanggil saat tombol diklik.

  1. Impor hal berikut:
import androidx.compose.material.Switch
  1. Dalam fungsi RoundTipRow(), tambahkan parameter roundUp dari jenis Boolean dan fungsi lambda onRoundUpChanged yang menggunakan Boolean dan tidak menampilkan apa pun:
@Composable
fun RoundTheTipRow(
   roundUp: Boolean,
   onRoundUpChanged: (Boolean) -> Unit,
   modifier: Modifier = Modifier
)

Tindakan ini akan mengangkat status tombol.

  1. Pada composable Switch, tambahkan modifier ini untuk meratakan composable Switch ke akhir layar:
       Switch(
           modifier = modifier
               .fillMaxWidth()
               .wrapContentWidth(Alignment.End),
           //...
       )
  1. Impor hal berikut:
import androidx.compose.foundation.layout.wrapContentWidth
  1. Dalam fungsi TipTimeScreen(), tambahkan variabel var untuk status composable Switch. Buat variabel var bernama roundUp, tetapkan ke mutableStateOf(), dengan false sebagai argumen default. Gabungkan panggilan dengan remember { }.
fun TipTimeScreen() {
   //...
   var roundUp by remember { mutableStateOf(false) }

   //...
   Column(
       ...
   ) {
     //...
  }
}

Ini adalah variabel untuk status composable Switch, dan false akan menjadi status default.

  1. Di blok Column dari fungsi TipTimeScreen() setelah kolom teks Tip %, panggil fungsi RoundTheTipRow() dengan argumen berikut: parameter bernama roundUp ditetapkan ke roundUp dan parameter bernama onRoundUpChanged ditetapkan ke callback lambda yang mengupdate nilai roundUp:
@Composable
fun TipTimeScreen() {
   //...

   Column(
       ...
   ) {
       Text(
           ...
       )
       Spacer(...)
       EditNumberField(
           ...
       )
       EditNumberField(
           ...
       )
       RoundTheTipRow(roundUp = roundUp, onRoundUpChanged = { roundUp = it })
       Spacer(...)
       Text(
           ...
       )
   }
}

Tindakan ini akan menampilkan baris Round up tip.

  1. Jalankan aplikasi. Aplikasi menampilkan tombol Round up tip?, tetapi thumb tombol hampir tidak terlihat seperti yang dapat Anda lihat dalam gambar ini:

Tombol yang tidak dipilih dan dipilih dengan angka yang mengidentifikasi 2 elemen dan status1. Thumb
2. Track

Anda meningkatkan visibilitas thumb di langkah berikutnya dengan mengubahnya menjadi abu-abu gelap.

  1. Pada composable Switch() fungsi RoundTheTipRow(), tambahkan parameter bernama colors.
  2. Tetapkan parameter bernama colors ke fungsi SwitchDefaults.colors() yang menerima parameter bernama uncheckedThumbColor yang ditetapkan ke argumen Color.DarkGray.
Switch(
   //...
   colors = SwitchDefaults.colors(
       uncheckedThumbColor = Color.DarkGray
   )
)
  1. Impor hal berikut:
import androidx.compose.material.SwitchDefaults
import androidx.compose.ui.graphics.Color

Fungsi composable RoundTheTipRow() kini akan terlihat seperti cuplikan kode ini:

@Composable
fun RoundTheTipRow(roundUp: Boolean, onRoundUpChanged: (Boolean) -> Unit) {
   Row(
       modifier = Modifier
           .fillMaxWidth()
           .size(48.dp),
       verticalAlignment = Alignment.CenterVertically
   ) {
       Text(stringResource(R.string.round_up_tip))
       Switch(
           modifier = Modifier
               .fillMaxWidth()
               .wrapContentWidth(Alignment.End),
           checked = roundUp,
           onCheckedChange = onRoundUpChanged,
           colors = SwitchDefaults.colors(
               uncheckedThumbColor = Color.DarkGray
           )
       )
   }
}
  1. Jalankan aplikasi. Warna thumb tombol berbeda, seperti yang dapat Anda lihat dalam gambar ini:

24370de6d667a700.png

  1. Masukkan jumlah tagihan dan persentase tip, lalu pilih tombol Round up tip?. Jumlah tip tidak dibulatkan karena Anda masih perlu mengupdate fungsi calculateTip(), yang akan Anda lakukan di bagian berikutnya.

Update fungsi calculateTip() untuk membulatkan tip

Ubah fungsi calculateTip() untuk menerima variabel Boolean agar membulatkan tip ke bilangan bulat terdekat:

  1. Untuk membulatkan tip, fungsi calculateTip() harus mengetahui status tombol, yaitu Boolean. Di fungsi calculateTip(), tambahkan parameter roundUp dari jenis Boolean:
private fun calculateTip(
   amount: Double,
   tipPercent: Double = 15.0,
   roundUp: Boolean
): String {
   //...
}
  1. Dalam fungsi calculateTip() sebelum pernyataan return, tambahkan kondisi if() yang memeriksa nilai roundUp. Jika roundUp bernilai true, tentukan variabel tip dan tetapkan ke fungsi kotlin.math.ceil(), lalu teruskan fungsi tip sebagai argumen:
if (roundUp)
   tip = kotlin.math.ceil(tip)

Fungsi calculateTip() yang telah selesai akan terlihat seperti cuplikan kode ini:

private fun calculateTip(amount: Double, tipPercent: Double = 15.0, roundUp: Boolean): String {
   var tip = tipPercent / 100 * amount
   if (roundUp)
       tip = kotlin.math.ceil(tip)
   return NumberFormat.getCurrencyInstance().format(tip)
}
  1. Di fungsi TipTimeScreen(), update panggilan fungsi calculateTip(), lalu teruskan parameter roundUp:
val tip = calculateTip(amount, tipPercent, roundUp)
  1. Jalankan aplikasi. Sekarang, jumlah tip dibulatkan seperti yang dapat Anda lihat pada gambar berikut:

7. Mendapatkan kode solusi

Guna mendownload kode untuk codelab yang sudah selesai, Anda dapat menggunakan perintah git ini:

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-tip-calculator.git

Atau, Anda dapat mendownload repositori sebagai file zip, mengekstraknya, dan membukanya di Android Studio.

Jika Anda ingin melihat kode solusi, lihat di GitHub.

8. Kesimpulan

Selamat! Anda telah menambahkan fungsi tip kustom ke Aplikasi Tip Time. Sekarang, dengan aplikasi tersebut, pengguna dapat memasukkan persentase tip kustom dan membulatkan jumlah tip. Bagikan hasil karya Anda di media sosial dengan hashtag #AndroidBasics!

Pelajari lebih lanjut