Roll Magic
Acum că toate elementele compozabile necesare sunt prezente, vom modifica aplicația astfel încât o atingere a butonului să arunce zarurile.
/* MainActivity.kt */
fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
var result = 1
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(R.drawable.dice_1),
contentDescription = "1"
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { result = (1..6).random() }) {
Text(stringResource(R.string.roll))
}
}
}
1. În funcția DiceWithButtonAndImage()
, înainte de funcția Column()
, creăm o variabilă result
și o setăm la valoarea 1.
2. Privim la elementul compozabil Button
. Vom observa că i se transmite un parametru onClick
care este setat cu o pereche de acolade conținând comentariul /*TODO*/
. Acoladele, în acest caz, reprezintă ceea ce se numește o lambda, zona din interiorul acoladelor fiind corpul lambda. Când o funcție este transmisă ca argument, poate fi denumită și "callback".
/* MainActivity.kt */
Button(onClick = { /*TODO*/ })
O lambda este o funcție literală, care este o funcție ca oricare alta, dar în loc să fie declarată separat cu cuvântul cheie fun
, este scrisă inline și transmisă ca expresie. Elementul compozabil Button
așteaptă să i se transmită o funcție ca parametru onClick
. Acesta este locul perfect pentru a utiliza o lambda, și vom scrie corpul lambda în această secțiune.
3. În funcția Button()
, eliminăm comentariul /*TODO*/
din valoarea corpului lambda al parametrului onClick
.
4. O aruncare de zaruri este aleatorie. Pentru a reflecta acest lucru în cod, trebuie să folosim sintaxa corectă pentru a genera un număr aleatoriu. În Kotlin, putem utiliza metoda random()
pe un interval de numere. În corpul lambda al onClick
, setăm variabila result
la un interval între 1 și 6 și apoi apelăm metoda random()
pe acel interval. Ne amintim că, în Kotlin, intervalele sunt desemnate prin două puncte între primul număr din interval și ultimul număr din interval.
Acum putem interactiona cu butonul, dar mai avem de implementat functionalitatea din spatele lui.
Adăugăm o condiție la aplicația de aruncare a zarurilor
Pana acum, am creat o variabilă result
și am setat-o manual la valoarea 1. În
cele din urmă, valoarea variabilei result
este resetată când butonul Roll
este atins și ar trebui să determine ce imagine este afișată.
Elementele compozabile sunt fără stare în mod implicit, ceea ce înseamnă că nu
păstrează o valoare și pot fi recompuse oricând de către sistem, rezultând în
resetarea valorii. Cu toate acestea, Compose oferă o modalitate convenabilă de
a evita acest lucru. Funcțiile compozabile pot stoca un obiect în memorie
utilizând elementul compozabil remember
.
/* MainActivity.kt */
var result by remember { mutableStateOf(1) }
1. Facem variabila result
un element compozabil remember
. Elementul compozabil remember
necesită transmiterea unei funcții.
2. În corpul elementului compozabil remember
, transmitem o funcție mutableStateOf()
și apoi îi transmitem acestei funcții argumentul 1. Funcția mutableStateOf()
returnează un observabil. Vom învăța mai multe despre observabile mai târziu, dar pentru moment, acest lucru înseamnă practic că atunci când valoarea variabilei result
se schimbă, se declanșează o recompunere, valoarea lui result
este reflectată, iar interfața utilizator se reîmprospătează.
Acum, când butonul este atins, variabila result
este actualizată cu o valoare de număr aleatoriu.
3. Sub instanțierea variabilei result
, creăm o variabilă imutabilă imageResource
setată la o expresie when
care acceptă variabila result
și apoi setăm fiecare rezultat posibil la resursa sa drawable.
/* MainActivity.kt */
val imageResource = when (result) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
4. Schimbăm ID-ul transmis parametrului painterResource
al elementului compozabil Image
de la resursa R.drawable.dice_1
la variabila imageResource
.
5. Schimbăm parametrul contentDescription
al elementului compozabil Image
pentru a reflecta valoarea variabilei result
prin convertirea variabilei result
la un șir de caractere cu toString()
și transmiterea acestuia ca contentDescription
.
/* MainActivity.kt */
Image(
painter = painterResource(imageResource),
contentDescription = result.toString()
)
6. Rulăm aplicația noastră. Solutia acestui exercitiu o gasiti aici