W tym ćwiczeniu dodasz kości do dotychczasowej aplikacji Dice Roller na Androida. Najpierw ukończ poprzednie ćwiczenia z programowania.
Zamiast pokazywać wartość rzutu kostką w aplikacji TextView
, aplikacja wyświetli odpowiedni obraz kości do odsłoniętej strony. Aplikacja będzie o wiele lepsza i bardziej czytelna.
Otrzymasz link do pobrania kostek. Możesz je też dodać jako zasoby w aplikacji. Aby napisać kod, z którego użyjesz kości, użyjesz instrukcji when
w Kotlinie.
Wymagania wstępne
- Ukończ ćwiczenia z programowania Create the Roller Roller na Androida, które mają przycisk.
- Możliwość zapisu instrukcji sterowania (
if / else
,when
). - Możliwość aktualizowania interfejsu aplikacji na podstawie danych wejściowych użytkownika (modyfikowanie pliku
MainActivity.kt
). - Możliwość dodania detektora kliknięć do elementu
Button.
- Możliwość dodawania zasobów graficznych do aplikacji na Androida.
Czego się nauczysz
- Jak zaktualizować
ImageView
, gdy aplikacja jest uruchomiona. - Jak dostosować działanie aplikacji w zależności od różnych warunków (za pomocą instrukcji
when
).
Co stworzysz
- Aplikacja na rolkę z kółkiem na urządzeniu z atrybutem
Button
, aby rzucić kostką i zaktualizować obraz na ekranie.
Wymagania
- Komputer z zainstalowaną aplikacją Android Studio.
- Połączenie internetowe do pobierania zdjęć kości.
W tym zadaniu zastąpisz TextView
układem ImageView
, który wyświetla obraz wyniku rzutu kostką.
Otwórz aplikację Dice Roller
- Uruchom i uruchom aplikację Dice Roller w aplikacji Create Diroll Roller na Androida za pomocą przycisku w Android Studio.
Aplikacja powinna wyglądać tak.
- Otwórz plik
activity_main.xml
(app > res > układ > activity_main.xml).
Otworzy się edytor układu.
Usuwanie widoku tekstowego
- W Edytorze układu wybierz
TextView
w Drzewie komponentów.
.
- Kliknij prawym przyciskiem myszy i wybierz Usuń lub naciśnij klawisz
Delete
. - Na razie zignoruj ostrzeżenie widoczne na urządzeniu
Button
. W następnym kroku naprawisz to.
Dodawanie elementu ImageView w układzie
- Przeciągnij ikonę
ImageView
z palety do widoku Projekt, umieszczając ją nadButton
.
- W oknie Wybierz zasób w sekcji Przykładowe dane kliknij awatar. Tego obrazu będziesz używać do czasu dodania kolejnych kości do następnego zadania.
- Naciśnij OK. Widok aplikacji powinien wyglądać tak: Projekt.
- W drzewie komponentów widać 2 błędy. Obiekt
Button
nie jest ograniczony w pionie, aImageView
nie ma takiego ograniczenia.
Button
nie jest ograniczony w pionie, ponieważ usunięto element TextView
, poniżej którego został pierwotnie umieszczony. Teraz musisz umieścić element ImageView
i Button
pod spodem.
Określanie położenia obrazu i przycisku
ImageView
musi znaleźć się w pionie, niezależnie od tego, gdzie znajduje się obiekt Button
.
- Dodaj ograniczenia poziome do obiektu
ImageView
. Połącz lewą stronę elementuImageView
z lewej krawędzi elementu nadrzędnegoConstraintLayout
. - Połącz prawą stronę elementu
ImageView
z prawą krawędzią obiektu nadrzędnego.
Spowoduje to wyśrodkowanie obiektuImageView
w elemencie nadrzędnym.
- Dodaj ograniczenie pionowe do elementu
ImageView
, który łączy górną część obiektuImageView
z górną krawędzią elementu nadrzędnego.
ElementImageView
zostanie przesunięty do góry kolumnyConstraintLayout
. - Dodaj ograniczenie pionowe do elementu
Button
, który łączy górną część obiektuButton
z dolną krawędzią obszaruImageView
.
ElementButton
przesunie się w dół pod elementemImageView
. - Ponownie wybierz
ImageView
i dodaj ograniczenie w pionie łączące dolną częśćImageView
na dole elementu nadrzędnego.
WyśrodkujeImageView
w pionie wConstraintLayout
.
Wszystkie ostrzeżenia o ograniczeniach powinny zostać usunięte.
W efekcie widok Projekt powinien wyglądać tak jak poniżej, ImageView
z środkiem, a Button
poniżej.
Na stronie ImageView
w drzewie komponentów może pojawić się ostrzeżenie o dodaniu opisu treści do obiektu ImageView
. Na razie nie martw się tym ostrzeżeniem, ponieważ później w ćwiczeniach z programowania skonfigurujesz opis treści dla ImageView
na podstawie tego, który obraz kości widzisz. Ta zmiana zostanie dokonana w kotlinie.
W tym zadaniu pobierzesz zdjęcia kości i dodasz je do aplikacji.
Pobieranie kości
- Otwórz ten adres URL, by pobrać na komputer plik ZIP z kostkami. Zaczekaj na zakończenie pobierania.
- Znajdź plik na komputerze (prawdopodobnie jest to folder Pobrane).
- Aby rozpakować plik, kliknij go dwukrotnie. Spowoduje to utworzenie nowego folderu
DiceImages
z 6 plikami kości do wyświetlania liczb od 1 do 6.
Dodaj obrazy kości do aplikacji
- W Android Studio kliknij kolejno Wyświetl > Narzędzie Windows i Menedżer zasobów w menu lub kartę Menedżer zasobów po lewej stronie okna Projekt.
- Kliknij + poniżej Menedżera zasobów i wybierz Importuj obiekty rysowane. Otworzy się przeglądarka plików.
- Znajdź i wybierz 6 plików z kostkami. Możesz zaznaczyć pierwszy plik, a potem przytrzymać klawisz
Shift
, aby wybrać pozostałe pliki. - Kliknij Otwórz.
- Kliknij Dalej, a następnie Importuj, aby potwierdzić, że chcesz zaimportować te 6 zasobów.
- Po zaimportowaniu plików 6 obrazów powinno pojawić się na liście aplikacji Do rysowania.
Dobra robota! W następnym zadaniu użyjesz tych obrazów w swojej aplikacji.
Ważne: – W będzie można odwoływać się do tych obrazów w kodzie Kotlin, podając ich identyfikatory zasobów:
R.drawable.dice_1
R.drawable.dice_2
R.drawable.dice_3
R.drawable.dice_4
R.drawable.dice_5
R.drawable.dice_6
Zastąp przykładowy awatar
- W edytorze projektów wybierz
ImageView
. - W sekcji Atrybuty w sekcji Zadeklarowane atrybuty znajdź atrybut srcCompat ustawiony na zdjęcie awatara.
Pamiętaj, że atrybut srcCompat narzędzia wykorzystuje przesłany obraz tylko w widoku projektowania Androida Studio. Obraz będzie widoczny tylko dla deweloperów podczas tworzenia aplikacji, ale nie będzie widoczny podczas uruchamiania w emulatorze lub na urządzeniu.
- Kliknij mały awatar. Otworzy się okno dialogowe, w którym możesz wybrać nowy zasób do użycia z elementem
ImageView
.
- Wybierz element
dice_1
, który można rysować, i kliknij OK.
Wow! ImageView
zajmuje cały ekran.
Następnie dostosujesz szerokość i wysokość obiektu ImageView
, przez co obiekt Button
nie zostanie ukryty.
- W oknie Atrybuty w sekcji Widżety ograniczeń znajdź atrybuty layout_width i layout_height. Obecnie ustawienie ma wartość wrap_content, co oznacza, że wartość
ImageView
jest równa wysokości elementu (obrazu źródłowego). - Zamiast tego ustaw stałą szerokość 160 dp i stałą wysokość 200 dp na
ImageView
. Naciśnij Enter.
UrządzenieImageView
jest teraz znacznie mniejsze.
Button
może być trochę za blisko obrazu.
- Dodaj górny margines do przycisku o rozmiarze 16 dp, ustawiając go w widżecie ograniczeń.
Po zmianie widoku Projekt aplikacja wygląda znacznie lepiej.
Zmiana obrazu kości po kliknięciu przycisku
Układ został rozwiązany, ale musisz zaktualizować klasę MainActivity
, by używała kości do gry.
W aplikacji MainActivity.kt
występuje błąd. Jeśli spróbujesz uruchomić aplikację, zobaczysz ten błąd kompilacji:
Dzieje się tak, ponieważ Twój kod nadal odwołuje się do elementu TextView
, który został usunięty z układu.
- Otwórz
MainActivity.kt
(app > java > com.example.diceroller > MainActivity.kt)
Kod odnosi się do elementu R.id.textView
, ale Android Studio go nie rozpoznaje.
- W metodzie
rollDice()
wybierz kod, który odwołuje się doTextView
, i go usuń.
// Update the TextView with the dice roll
val resultTextView: TextView = findViewByID(R.id.textView)
resultTextView.text = dice.roll().toString()
- W
rollRice()
utwórz nową zmienną o nazwiediceImage
typuImageView
. Ustaw jego wartość naImageView
z układu. Użyj metodyfindViewById()
i przekaż identyfikator zasobuImageView
,R.id.imageView
jako argumentu wejściowego.
val diceImage: ImageView = findViewById(R.id.imageView)
Jeśli nie wiesz, jak znaleźć dokładny identyfikator zasobu ImageView
, sprawdź identyfikator u góry okna Atrybuty.
Gdy odwołujesz się do tego identyfikatora zasobu w kotlinie, wpisz go dokładnie w ten sam sposób (małe litery i V, bez spacji). W przeciwnym razie w Android Studio pojawi się błąd.
- Dodaj ten wiersz kodu, aby przetestować, czy
ImageView
jest prawidłowo aktualizowany po kliknięciu przycisku. Gry z kośćmi nie zawsze są „2” – po prostu użyj obrazudice_2
do testów.
diceImage.setImageResource(R.drawable.dice_2)
Ten kod wywołuje metodę setImageResource()
w obiekcie ImageView
, przekazując identyfikator zasobu obrazu dice_2
. ImageView
na ekranie zaktualizuje się i wyświetli obraz dice_2
.
Metoda rollDice()
powinna teraz wyglądać tak:
private fun rollDice() {
val dice = Dice(6)
val diceRoll = dice.roll()
val diceImage: ImageView = findViewById(R.id.imageView)
diceImage.setImageResource(R.drawable.dice_2)
}
- Uruchom aplikację, aby sprawdzić, czy działa bez błędów.
Aplikacja powinna zacząć od pustego ekranu z wyjątkiem przycisku Rolka.
Po kliknięciu przycisku pojawi się obraz kości z wartością 2. Tak!
Udało Ci się zmienić obraz na podstawie przycisku. Jesteś coraz bliżej celu
Niewątpliwie rzut kostką nie będzie zawsze remisem. Użyj mechanizmów zdobytych w ramach ćwiczenia Dodawanie warunkowych do różnych rzutów kostką, by odpowiednio dopasować kości do wyświetlenia na ekranie w zależności od losowej rzutu kostką.
Zanim zaczniesz pisać kod, zastanów się, jak powinna działać aplikacja, pisząc pseudokod, który opisuje, co powinno się stać. Przykład:
Jeśli użytkownik ma wartość 1, wyświetl obraz dice_1
.
Jeśli użytkownik ma 2, wyświetl obraz dice_2
.
itd.
Powyższy pseudokod może zostać zapisany w formie instrukcji if / else
w Kotlinie na podstawie wartości rzutu kostką.
if (diceRoll == 1) {
diceImage.setImageResource(R.drawable.dice_1)
} else if (diceRoll == 2) {
diceImage.setImageResource(R.drawable.dice_2)
}
...
Jednak pisanie if / else
każdego przypadku jest dość powtarzalne. Te same zasady można wyrazić w formie when
. To bardziej zwięzłe (mniej kodu). Skorzystaj z tej metody w aplikacji.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
...
Zaktualizuj metodę rollDice()
- W metodzie
rollDice()
usuń wiersz kodu, który za każdym razem ustawia identyfikator zasobu obrazu nadice_2
.
diceImage.setImageResource(R.drawable.dice_2)
- Zastąp go instrukcją
when
, która aktualizuje elementImageView
na podstawie wartościdiceRoll
.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
Po wprowadzeniu zmian metoda rollDice()
powinna wyglądać podobnie do tego.
private fun rollDice() {
val dice = Dice(6)
val diceRoll = dice.roll()
val diceImage: ImageView = findViewById(R.id.imageView)
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
}
- Uruchom aplikację. Kliknięcie przycisku Rzuć powoduje zmianę obrazu kości poza inne niż 2. Udało się
Zoptymalizuj kod
Jeśli chcesz napisać jeszcze bardziej zwięzły kod, możesz wprowadzić zmianę w tym kodzie. Nie ma to wpływu na użytkowników aplikacji, ale sprawi, że kod będzie krótszy i mniej powtarzalny.
Zauważysz, że wywołanie diceImage.setImageResource()
pojawia się w instrukcji wyciągu 6 razy.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
Zmieniają się jedynie identyfikatory używanych zasobów. Oznacza to, że możesz utworzyć zmienną do przechowywania identyfikatora zasobu. Następnie możesz wywołać diceImage.setImageResource()
tylko raz w kodzie i przekazać prawidłowy identyfikator zasobu.
- Zastąp powyższy kod poniższym kodem.
val drawableResource = when (diceRoll) {
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
6 -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
Nową koncepcją jest to, że wyrażenie when
może zwracać wartość. W nowym fragmencie kodu wyrażenie when
zwraca prawidłowy identyfikator zasobu, który zostanie zapisany w zmiennej drawableResource
. Następnie za pomocą tej zmiennej możesz zaktualizować wyświetlony zasób graficzny.
- Zwróć uwagę na podkreślone na czerwono pole
when
. Gdy najedziesz na niego kursorem, zobaczysz komunikat o błędzie: 'Kiedy' wyrażenie musi być obszerne, dodaj wymagany oddział „&&33;in&&33; gałąź”.
Błąd wynika z tego, że wartość wyrażenia when
jest przypisana do wartości drawableResource
. Element when
musi więc być kompletny – musi obsługiwać wszystkie możliwe przypadki, aby wartość była zawsze zwracana, nawet jeśli zmienisz kości na 12 boków. Android Studio zaleca dodanie gałęzi else
. Możesz rozwiązać ten problem, zmieniając zgłoszenie gry 6
na else
. Zgłoszenia od 1
do 5
są takie same, ale wszystkie pozostałe, w tym 6
, są obsługiwane przez else
.
val drawableResource = when (diceRoll) {
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
}
diceImage.setImageResource(drawableResource)
- Uruchom aplikację, aby upewnić się, że nadal działa prawidłowo. Sprawdź to na tyle, aby upewnić się, że wszystkie liczby są wyświetlane na obrazach od 1 do 6.
Ustawianie odpowiedniego opisu treści w elemencie ImageView
Po zastąpieniu numeru na grafice czytniki ekranu nie będą już wiedziały, która wartość została rzucona. Aby rozwiązać ten problem, zaktualizuj zasób graficzny ImageView
. Opis treści powinien być tekstem, który wyświetla się w ImageView
, aby czytniki ekranu mogły go opisać.
diceImage.contentDescription = diceRoll.toString()
Czytnik ekranu może odczytać ten opis zawartości, więc jeśli na ekranie wyświetli się obraz kostki "6", opis treści zostanie odczytany na głos tak jak w &"6.
Przydatniejsze uruchamianie
Gdy użytkownik otwiera aplikację po raz pierwszy, jest ona pusta (z wyjątkiem przycisku Rolka), co wygląda nietypowo. Użytkownicy mogą nie wiedzieć, czego mogą się spodziewać, dlatego po uruchomieniu aplikacji i utworzeniu funkcji Activity
zmień interfejs, by wyświetlać losową kostkę. Użytkownicy z większym prawdopodobieństwem zrozumieją, że kliknięcie przycisku Rzuć spowoduje rzut kostką.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener { rollDice() }
// Do a dice roll when the app starts
rollDice()
}
Skomentuj kod
Dodaj kilka komentarzy do kodu, aby opisać, co się dzieje w napisanym kodzie.
Tak może wyglądać Twoja metoda rollDice()
.
/**
* Roll the dice and update the screen with the result.
*/
private fun rollDice() {
// Create new Dice object with 6 sides and roll the dice
val dice = Dice(6)
val diceRoll = dice.roll()
// Find the ImageView in the layout
val diceImage: ImageView = findViewById(R.id.imageView)
// Determine which drawable resource ID to use based on the dice roll
val drawableResource = when (diceRoll) {
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
}
// Update the ImageView with the correct drawable resource ID
diceImage.setImageResource(drawableResource)
// Update the content description
diceImage.contentDescription = diceRoll.toString()
}
Pełny plik MainActivity.kt
znajdziesz w kodzie rozwiązań podanym na GitHubie, do którego link znajdziesz poniżej.
Super Ci poszło! Teraz możesz dodać tę aplikację do kolejnej nocy z przyjaciółmi!
Kod rozwiązania tego ćwiczenia z programowania znajdziesz w projekcie i module przedstawionym poniżej.
Aby pobrać kod z ćwiczenia z programowania na GitHubie i otworzyć go w Android Studio, wykonaj te czynności.
- Włącz Android Studio.
- W oknie Witamy w Android Studio kliknij Sprawdź projekt na podstawie kontroli wersji.
- Wybierz Git.
- W oknie Kopiowanie repozytorium wklej podany adres URL kodu w polu URL.
- Kliknij przycisk Przetestuj, poczekaj, aż pojawi się zielony dymek z informacją Połączenie uda się.
- Opcjonalnie zmień Katalog na inny niż sugerowane wartości domyślne.
- Kliknij Kopiuj. Android Studio zacznie pobierać kod.
- W wyskakującym okienku Kontrola wersji kliknij Tak.
- Poczekaj na otwarcie Android Studio.
- Wybierz odpowiedni moduł dla początków programowania lub kodu rozwiązania.
- Kliknij przycisk Uruchom , by utworzyć i uruchomić kod.
- Użyj funkcji setImageResource(), aby zmienić obraz wyświetlany w elemencie
ImageView
. - Używaj instrukcji sterowania, na przykład wyrażeń
if / else
lubwhen
do obsługi różnych przypadków w aplikacji, np. wyświetlania różnych obrazów w różnych okolicznościach.
Wykonaj te czynności:
- Dodaj kolejną kostkę do aplikacji, by jeden przycisk Rzut dał 2 wyniki. Ile elementów (
ImageViews
) będziesz potrzebować w układzie? Jak wpłynie to na kodMainActivity.kt
?
Sprawdzanie zadań:
Gdy aplikacja będzie działać, powinna wyświetlić się bezbłędnie.