Te ćwiczenia są częścią kursu Android Kotlin Fundamentals. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. Wszystkie ćwiczenia z kursu są wymienione na stronie docelowej ćwiczeń z programowania na temat Kotlin.
Wprowadzenie
Dzięki nim dowiesz się, jak ulepszyć aplikację DiceRoller z ostatniego ćwiczenia z programowania, a także jak dodawać zasoby graficzne i jak z nich korzystać. Poznasz również zgodność aplikacji z różnymi wersjami Androida oraz dowiesz się, jak może Ci w tym pomóc pakiet Jetpack dla Androida.
Co warto wiedzieć
- Jak utworzyć nowy projekt aplikacji i uruchomić ją w emulatorze lub na urządzeniu fizycznym.
- Podstawowe komponenty projektu aplikacji, w tym katalog (
res
) i pliki kompilacji Gradle. - Jak edytować plik układu aplikacji.
- Znajdowanie i modyfikowanie obiektów widoku w kodzie aplikacji.
Czego się nauczysz:
- Jak dodać pliki do zasobów aplikacji.
- Jak używać obrazów w układzie aplikacji.
- Jak skuteczniej znaleźć wyświetlenia w kodzie aplikacji.
- Jak używać zastępczych obrazów w projekcie aplikacji z przestrzenią nazw XML.
- Informacje o poziomach interfejsu API Androida i o tym, jak sprawdzić minimalny, docelowy i skompilowany poziom interfejsu API.
- Jak korzystać z bibliotek Jetpacka w swojej aplikacji do obsługi starszych wersji Androida.
Co chcesz
- Zmodyfikuj aplikację DiceRoller z ostatniego ćwiczenia z programowania, tak by uwzględnić liczbę obrazów, a nie liczbę.
- Dodaj pliki graficzne do zasobów aplikacji.
- Zaktualizuj układ i kod aplikacji tak, aby zamiast wartości liczbowej używał obrazów.
- Zaktualizuj swój kod, aby efektywniej znajdować wyświetlenia.
- Zaktualizuj kod, aby po uruchomieniu aplikacji używać pustego obrazu.
- Zaktualizuj aplikację, aby korzystać z bibliotek Android Jetpack do zapewnienia zgodności wstecznej ze starszymi wersjami Androida.
W tym ćwiczeniu tworzysz aplikację DiceRoller rozpoczętą w poprzednim ćwiczeniach z ćwiczenia i dodajesz kości do zmiany, gdy rzucisz kostką. Ostateczna wersja aplikacji DiceRoller wygląda tak:
Jeśli nie przeprowadzono ostatniego ćwiczenia z programowania, aplikację startową możesz pobrać tutaj: DiceRoller.
Na koniec ostatniego ćwiczenia z programowania masz aplikację, która za każdym razem, gdy użytkownik kliknie przycisk, aktualizuje widok tekstowy o liczbie od 1 do 6. Ta aplikacja nazywa się DiceRoller, a nie 1–6 generatorów liczb, więc lepiej byłoby, gdyby kości były do niej podobne. W tym zadaniu dodasz obrazy do kości. Potem zamiast aktualizować tekst po naciśnięciu przycisku, wymieniasz inny obraz dla każdego wyniku.
Krok 1. Dodaj obrazy
- Otwórz projekt aplikacji DiceRoller w Android Studio, jeśli nie jest jeszcze otwarty. Jeśli nie udało Ci się ukończyć ostatniego ćwiczenia z programowania, możesz pobrać aplikację tutaj: DiceRoller.
- W widoku projektu w Androidzie rozwiń folder res i rozwiń folder draw.
Twoja aplikacja używa wielu różnych zasobów, w tym obrazów i ikon, kolorów, ciągów tekstowych oraz układów XML. Wszystkie te zasoby są przechowywane w folderzeres
. W folderzedrawable
musisz umieścić wszystkie zasoby graficzne aplikacji. W folderzedrawable
znajdziesz zasoby programu uruchamiającego aplikację. - Kliknij dwukrotnie plik ic_launch_background.xml. Są to pliki XML, które opisują ikonę jako obraz wektorowy. Wektory umożliwiają rysowanie obrazów w różnych rozmiarach i rozdzielczości. Obrazy bitmap, takie jak PNG lub GIF, mogą wymagać skalowania na różnych urządzeniach, co może spowodować utratę jakości.
- Kliknij Podgląd w prawej kolumnie edytora XML, aby wyświetlić wektorowy rysunek.
- Pobierz zdjęcia kości do swojej aplikacji z DiceImages.zip. Rozpakuj archiwum. Zbiór folderów XML powinien wyglądać tak:
- W Android Studio kliknij menu u góry widoku projektu, które obecnie wyświetla Android, i wybierz Projekt. Zrzut ekranu poniżej przedstawia, jak wygląda aplikacja w systemie plików.
- Rozwiń sekcję giceRoller > app > src > main > res > pull.
- Przeciągnij wszystkie pliki XML z folderu
DiceImages
do folderu Android Studio i do rysunkowego folderu. Kliknij OK.
- Przełącz projekt z powrotem na widok Android. Zwróć uwagę, że pliki XML obrazu z kością znajdują się w rysunkowym folderze.
- Kliknij dwukrotnie
dice_1.xml
. Zwróć uwagę na kod XML tego obrazu. Kliknij przycisk Podgląd, aby zobaczyć, jak wygląda wektorowy obiekt rysowalny.
Krok 2. Zaktualizuj układ, aby używać obrazów
Teraz, gdy masz w folderze res/drawables
pliki obrazów kości, możesz uzyskać do nich dostęp za pomocą układu i kodu aplikacji. W tym kroku zastępujesz TextView
wartościami, które wyświetlają obrazy, wartością ImageView
.
- Otwórz plik z układem
activity_main.xml
, jeśli nie jest jeszcze otwarty. Kliknij kartę Tekst, aby wyświetlić kod XML układu. - Usuń element
<TextView>
. - Dodaj element
<ImageView>
o tych atrybutach:
<ImageView
android:id="@+id/dice_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/dice_1" />
Użyj ImageView
, by wyświetlić obraz w układzie. Jedyny nowy atrybut tego elementu to android:src
, który wskazuje zasób źródłowy obrazu. W tym przypadku źródło obrazu @drawable/dice_1
oznacza, że Android powinien poszukać w rysunkach zasobów (res/drawable
) obrazu o nazwie dice_1
.
- Kliknij przycisk Podgląd, aby wyświetlić podgląd układu. Powinno to wyglądać tak:
Krok 3. Zaktualizuj kod
- Otwórz aplikację
MainActivity
. Jak do tej pory działała funkcjarollDice()
:
private fun rollDice() {
val randomInt = Random().nextInt(6) + 1
val resultText: TextView = findViewById(R.id.result_text)
resultText.text = randomInt.toString()
}
Zauważ, że odwołanie do R.id.result_text
może być zaznaczone na czerwono, czyli że fragment TextView
został usunięty z układu i ten identyfikator już nie istnieje.
- Usuń dwa wiersze na końcu funkcji, która określa zmienną
resultText
, i ustaw jej właściwość tekstową. Nie korzystasz już z układuTextView
w układzie, więc nie potrzebujesz żadnego z tych wierszy. - Użyj atrybutu
findViewByID()
, aby uzyskać odniesienie do nowego elementuImageView
w układzie według identyfikatora (R.id.dice_image
), i przypisz ten widok do nowej zmiennejdiceImage
:
val diceImage: ImageView = findViewById(R.id.dice_image)
- Dodaj blok
when
, aby wybrać konkretny obraz na podstawie wartościrandomInteger
:
val drawableResource = when (randomInt) {
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
}
Podobnie jak w przypadku identyfikatorów, możesz odwoływać się do obrazów w rysunku w rysunku z wartościami w klasie R
. R.drawable
dotyczy folderu rysunkowego aplikacji, a dice_1
to konkretny zasób obrazu w tym folderze.
- Zaktualizuj źródło
ImageView
za pomocą metodysetImageResource()
i odwołania do znalezionego właśnie obrazu kostki.
diceImage.setImageResource(drawableResource)
- Skompiluj i uruchom aplikację. Gdy klikniesz przycisk Rolka, obraz powinien się zaktualizować, dodając odpowiedni obraz.
Wszystko w Twojej aplikacji działa, ale kodowanie to coś więcej niż kod, który będzie działał. Rozumiesz też, jak pisać skuteczne i działające aplikacje. Oznacza to, że aplikacje powinny działać prawidłowo, nawet jeśli użytkownik nie ma najdroższego urządzenia z Androidem lub najlepszej sieci. W miarę dodawania kolejnych funkcji aplikacje powinny nadal działać płynnie, a kod powinien być czytelny i dobrze zorganizowany.
W tym zadaniu poznasz jeden ze sposobów na zwiększenie wydajności aplikacji.
- Otwórz aplikację
MainActivity
, jeśli jeszcze nie jest otwarta. W metodzierollDice()
zwróć uwagę na deklarację zmiennejdiceImage
:
val diceImage : ImageView = findViewById(R.id.dice_image)
rollDice()
jest modułem obsługi kliknięć przycisku Rolka, więc za każdym razem, gdy użytkownik kliknie ten przycisk, aplikacja wywoła polecenie findViewById()
i odwoła się do tego elementu ImageView
. Najlepiej, aby liczba połączeń z adresem findViewById()
była jak najmniejsza, ponieważ system Android za każdym razem przeszukuje całą hierarchię widoków danych, co jest drogim procesem.
W małej aplikacji, takiej jak ta, nie jest to wielki problem. Jeśli korzystasz z bardziej złożonej aplikacji na wolniejszym telefonie, ciągłe wywoływanie findViewById()
może spowodować jej opóźnienie. Zamiast tego najlepiej wywołać raz element findViewById()
i zapisać obiekt View
w polu. Pozostawienie odniesienia do ImageView
w polu umożliwia systemowi bezpośredni dostęp do View
w dowolnym momencie, co zwiększa wydajność.
- U góry klasy przed
onCreate()
utwórz pole do przechowywania danychImageView
.
var diceImage : ImageView? = null
Najlepiej jest zainicjować tę zmienną tutaj, gdy jest ona deklarowana lub w konstruktorze, ale aktywności na Androidzie nie używają konstruktorów. Widoki w układzie są w ogóle niedostępne dla obiektów, dopóki nie zostaną zawyżone w metodzie onCreate()
przez wywołanie metody setContentView()
. Dopóki to się nie stanie, nie możesz inicjować zmiennej diceImage
.
Jedną z możliwości jest zdefiniowanie zmiennej diceImage
jako wartość null. Tak jak w tym przykładzie, Ustaw wartość null
, gdy zostanie zadeklarowana, a potem przypisz ją do rzeczywistego elementu ImageView
w onCreate()
za pomocą findViewById()
. Skomplikuje to Twój kod, bo teraz musisz sprawdzić wartość null
za każdym razem, gdy chcesz użyć diceImage
. Istnieje lepsze rozwiązanie.
- Zmień deklarację
diceImage
, by użyć słowa kluczowegolateinit
, i usuń przypisanienull
:
lateinit var diceImage : ImageView
Słowo kluczowe lateinit
obiecuje kompilator w Kotlin, że zmienna jest inicjowana przed wywołaniem kodu w dowolnych operacjach. W związku z tym nie musimy tutaj inicjować zmiennej na poziomie null
i możemy jej używać jako zmiennej niedopuszczającej wartości pustych. Sprawdzoną metodą jest użycie lateinit
z polami, które mają właśnie takie widoki.
- W
onCreate()
po metodziesetContentView()
użyjfindViewById()
, by uzyskaćImageView
.
diceImage = findViewById(R.id.dice_image)
- Usuń stary wiersz
rollDice()
w deklaracji i pobierzImageView
. Ten wiersz został wcześniej zastąpiony deklaracją pola.
val diceImage : ImageView = findViewById(R.id.dice_image)
- Ponownie uruchom aplikację, aby sprawdzić, czy nadal działa.
W tej chwili używasz dice_1
jako początkowego obrazu kości. Zamiast tego chcesz po prostu nie wyświetlać obrazu, dopóki kostka nie zostanie rzucona po raz pierwszy. Możesz to zrobić na kilka sposobów.
- Otwórz kartę
activity_layout.xml
na karcie Tekst. - W elemencie
<ImageView>
ustaw atrybutandroid:src
na"@drawable/empty_dice"
:
android:src="@drawable/empty_dice"
Obraz empty_dice
to jeden z obrazów pobranych i dodanych do folderu drawable
. Ma taki sam rozmiar jak inne kości, ale tylko ta jest pusta. To obraz, który wyświetli się po uruchomieniu aplikacji.
- Kliknij kartę Projekt. Obraz Dieda jest teraz pusty, ale w podglądzie też nie jest widoczny.
Powszechnie zdarza się, że zawartość projektu jest definiowana dynamicznie w czasie działania – na przykład w przypadku aplikacji pobierających dane z internetu prawdopodobnie zaczyna się pusty ekran. Podczas projektowania aplikacji warto mieć jednak coś w tym formacie, aby wiedzieć, co zamierzasz umieścić. - W systemie
activity_layout.xml
skopiuj wierszandroid:src
i wklej drugą kopię. Zmień słowo "android" na "narzędzia", aby oba atrybuty wyglądały następująco:
android:src="@drawable/empty_dice"
tools:src="@drawable/empty_dice" />
Tutaj zmieniono przestrzeń nazw XML tego atrybutu z domyślnej przestrzeni nazw android
na przestrzeń nazw tools
. Przestrzeń nazw tools
jest używana, gdy chcesz określić treść zastępczą, która ma być używana tylko na podglądzie lub w edytorze projektu w Android Studio. Atrybuty korzystające z przestrzeni nazw tools
są usuwane podczas kompilacji aplikacji.
Przestrzenie nazw służą do rozwiązywania niejasności w odniesieniu do atrybutów o tej samej nazwie. Na przykład oba te atrybuty w tagu <ImageView>
mają tę samą nazwę (src
), ale przestrzeń nazw jest inna.
- Przyjrzyj się elementowi
<LinearLayout>
w katalogu głównym pliku układu i zwróć uwagę na dwie zdefiniowane tutaj przestrzenie nazw.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
...
- Zmień atrybut
tools:src
w taguImageView
nadice_1
zamiastempty_dice
:
android:src="@drawable/empty_dice"
tools:src="@drawable/dice_1" />
Zwróć uwagę, że obraz dice_1
znajduje się teraz na podglądzie.
- Skompiluj i uruchom aplikację. Zauważ, że obraz kostki w aplikacji jest pusty, dopóki nie klikniesz Rzuć.
Jedną z wielkich zalet tworzenia aplikacji na Androida jest ogromna liczba urządzeń, na których działa Twój kod – od Nexus One po Pixel, tworząc urządzenia takie jak tablety, Pixelbooki, zegarki, telewizory czy samochody.
Podczas pisania na urządzeniu z Androidem nie musisz tworzyć osobnych aplikacji dla każdego z tych urządzeń – nawet te, które korzystają z bardzo różnych urządzeń, np. zegarków i telewizorów, i mogą współdzielić ten sam kod. Istnieją jednak pewne ograniczenia i strategie zgodności, o których musisz wiedzieć, aby stosować się do tych wymagań.
W tym zadaniu dowiesz się, jak kierować aplikację na określone poziomy interfejsu API Androida i jak używać bibliotek Android Jetpack do obsługi starszych urządzeń.
Krok 1. Poznaj poziomy interfejsu API
Podczas poprzedniego ćwiczenia z programowania dowiesz się, jaki poziom obsługi powinien obsługiwać Twoja aplikacja na Androida API. System operacyjny Android ma różne numery wersji, które wywodzą się z pysznych przysmaków uporządkowane w kolejności alfabetycznej. Każda wersja systemu operacyjnego ma nowe funkcje. Na przykład Android Oreo obsługuje aplikacje w obrazie w obrazie, a w Androidzie – wycinki. Poziomy interfejsu API odpowiadają wersjiom Androida. Na przykład interfejs API 19 odpowiada Androidowi 4.4 (KitKat).
Ze względu na wiele czynników, między innymi to, co obsługuje sprzęt, czy użytkownicy zdecydują się zaktualizować urządzenia i czy producenci obsługują różne poziomy systemu operacyjnego, użytkownicy nieuchronnie trafiają na urządzenia z różnymi wersjami systemu operacyjnego.
Podczas tworzenia projektu aplikacji określasz minimalny poziom interfejsu API, który obsługuje Twoja aplikacja. To znaczy, że określasz najstarszą wersję Androida obsługiwaną przez aplikację. Twoja aplikacja ma również poziom, na którym jest skompilowana, i na wymagany poziom. Każdy z tych poziomów jest parametrem konfiguracji w plikach kompilacji Gradle.
- Rozwiń folder Gradle Scripts i otwórz plik build.gradle (Module: app).
Ten plik definiuje parametry kompilacji i zależności konkretnej aplikacji. Plik build.gradle (Project: DiceRoller) określa parametry kompilacji dla całego projektu. W wielu przypadkach moduł aplikacji jest jedynym modułem w projekcie, więc ten segment może wyglądać na dowolny. Jeśli jednak Twoja aplikacja stanie się bardziej złożona i podzielisz ją na kilka części lub jeśli aplikacja obsługuje platformy takie jak zegarek z Androidem, w tym samym projekcie mogą pojawić się różne moduły. - Sprawdź sekcję
android
u góry plikubuild.gradle
. (przedstawiony poniżej przykład nie jest częścią całej sekcji, ale zawiera tematy, które najbardziej Cię interesują w tym ćwiczeniu z programowania).
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.android.diceroller"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
}
- Sprawdź parametr
compileSdkVersion
.
compileSdkVersion 28
Ten parametr określa poziom interfejsu API Androida, którego Gradle ma używać do kompilowania aplikacji. To najnowsza wersja Androida, którą obsługuje Twoja aplikacja. Oznacza to, że Twoja aplikacja może korzystać z funkcji interfejsu API uwzględnionych na tym poziomie interfejsu API i niższych. Aplikacja obsługuje interfejs API 28, który odpowiada Androidowi 9 (Pie).
- Sprawdź parametr
targetSdkVersion
w sekcjidefaultConfig
:
targetSdkVersion 28
Ta wartość to najnowsza wersja interfejsu API, który został przez Ciebie przetestowany. W wielu przypadkach jest to ta sama wartość co w przypadku compileSdkVersion
.
- Sprawdź parametr
minSdkVersion
.
minSdkVersion 19
Ten parametr jest najważniejszy z trzech, ponieważ określa najstarszą wersję Androida, na której będzie działać aplikacja. Na urządzeniach z systemem Android starszym niż ten poziom interfejsu API w ogóle nie można uruchomić aplikacji.
Wybór minimalnego poziomu API dla aplikacji może być trudnym zadaniem. Ustaw zbyt niski poziom interfejsu API i przegapisz nowsze funkcje systemu operacyjnego Android. Jeśli ustawisz ją na zbyt wysokim poziomie, aplikacja będzie mogła działać tylko na nowszych urządzeniach.
Gdy skonfigurujesz projekt i przejdziesz do miejsca, w którym możesz określić minimalny poziom interfejsu API aplikacji, kliknij Pomóż mi wybrać. Pojawi się okno Rozpowszechnianie wersji interfejsu API. To okno zawiera informacje o liczbie urządzeń z różnymi poziomami systemu operacyjnego oraz o funkcjach dodanych lub zmienionych na poziomie systemu. Możesz też zapoznać się z informacjami o wersji Androida i panelem, gdzie znajdziesz więcej informacji o wpływie obsługi poszczególnych poziomów interfejsu API.
Krok 2. Sprawdź zgodność
Projektowanie aplikacji na Androida o różnych poziomach zaawansowania jest typowym wyzwaniem dla deweloperów aplikacji. Dlatego zespół zajmujący się tworzeniem aplikacji na Androida dołożył wielu starań, aby Ci pomóc.
W 2011 roku zespół opublikował pierwszą bibliotekę pomocy, czyli bibliotekę opracowaną przez Google, która oferuje kompatybilne zajęcia i przydatne funkcje. W 2018 r. ogłosiliśmy wprowadzenie Androida Jetpack, czyli zbioru bibliotek obejmujących wiele wcześniejszych zajęć i funkcji dostępnych w bibliotece pomocy. Teraz udostępniamy ją także w bibliotece pomocy.
- Otwórz aplikację
MainActivity
. - Klasa
MainActivity
wykracza poza samą właściwośćActivity
, ale odAppCompatActivity
.
class MainActivity : AppCompatActivity() {
...
AppCompatActivity
to klasa zgodności, która zapewnia taka samą aktywność na różnych poziomach systemu operacyjnego.
- Kliknij symbol + obok wiersza, który zaczyna się od
import
, aby rozwinąć importowanie zajęć. KlasaAppCompatActivity
została zaimportowana z pakietuandroidx.appcompat.app
. Przestrzeń nazw bibliotek Android Jetpack toandroidx
. - Otwórz build.gradle (Moduł: aplikacja) i przewiń w dół do sekcji zależności.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.core:core-ktx:1.0.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}
Zwróć uwagę na zależność od biblioteki appcompat
, która jest częścią androidx
i zawiera klasę AppCompatActivity
.
Krok 3. Dodaj zgodność dla obiektów rysowalnych wektorowych
Wykorzystasz nową wiedzę dotyczącą przestrzeni nazw, Gradle i zgodności, aby wprowadzić ostateczne poprawki w swojej aplikacji, co pozwoli zoptymalizować jej rozmiar na starszych platformach.
- Rozwiń folder res i rozwiń folder draw. Kliknij dwukrotnie jeden z kostek.
Jak wcześniej wiesz, wszystkie obrazy kości to w rzeczywistości pliki XML, które określają kolor i kształt kości. Pliki tego typu są nazywane rysunkami wektorowymi. W pozycji rysunkowej wektora wygodniejsze jest stosowanie formatów map bitowych (takich jak PNG), które można skalować wektorowo, nie tracąc jakości. Rysowanie wektorowe jest też zwykle znacznie mniejsze niż w przypadku tego samego obrazu w formacie bitmap.
Ważne jest, aby zaznaczyć, że element rysowalny wektorowo jest obsługiwany w interfejsie API 21 i kolejnych. Minimalny pakiet SDK Twojej aplikacji jest ustawiony na interfejs API 19. Jeśli aplikacja została wypróbowana na urządzeniu lub w emulatorze API 19, wygląda na to, że aplikacja kompiluje się i działa normalnie. Jak to działa?
Gdy tworzysz aplikację, proces tworzenia Gradle tworzy plik PNG z każdego z plików wektorowych. Te pliki PNG są używane na każdym urządzeniu z Androidem w wersji starszej niż 21. Te dodatkowe pliki PNG zwiększają rozmiar aplikacji. Niepotrzebne aplikacje są świetne – spowalniają pobieranie plików i zajmują więcej urządzeń oraz ograniczone miejsce. Duże aplikacje mają większą szansę na odinstalowanie, a użytkownicy nie mogą pobrać ani anulować pobierania tych aplikacji.
Dobra wiadomość jest taka, że dostępna jest biblioteka zgodności Androida X do tworzenia obiektów wektorowych aż do poziomu API 7. - Otwórz build.gradle (Moduł: aplikacja). Dodaj ten wiersz do sekcji
defaultConfig
:
vectorDrawables.useSupportLibrary = true
- Kliknij przycisk Sync Now (Synchronizuj teraz). Za każdym razem, gdy plik
build.gradle
jest modyfikowany, musisz zsynchronizować pliki kompilacji z projektem. - Otwórz plik z układem
main_activity.xml
. Dodaj tę przestrzeń nazw do głównego tagu<LinearLayout>
, pod przestrzenią nazwtools
:
xmlns:app="http://schemas.android.com/apk/res-auto"
Przestrzeń nazw app
jest przeznaczona dla atrybutów pochodzących z niestandardowego kodu lub z bibliotek, a nie z podstawowej platformy Android.
- Zmień atrybut
android:src
elementu<ImageView>
naapp:srcCompat
.
app:srcCompat="@drawable/empty_dice"
Atrybut app:srcCompat
korzysta z biblioteki Androida X do obsługi obiektów wektorowych w starszych wersjach Androida – nawet na poziomie API 7.
- Utwórz i uruchom aplikację. Na ekranie nie będzie widać żadnych innych zmian, ale teraz aplikacja nie będzie musiała generować wygenerowanych plików PNG dla kości, niezależnie od tego, gdzie będą biegać, co oznacza mniejszy plik aplikacji.
Projekt na Android Studio: DiceRollerFinal
Wyzwanie: zmodyfikuj aplikację DiceRoller tak, aby zawierała 2 kości. Gdy użytkownik kliknie przycisk Rzut, każda kostka powinna mieć inną wartość.
Wskazówka: utwórz nową funkcję prywatną, aby uzyskać losowy obraz rysowalny i zwrócić liczbę całkowitą zasobu rysunkowego. Użyj tej funkcji w przypadku każdego obrazu matrycy.
private fun getRandomDiceImage() : Int { ... }
Kod rozwiązania testu zabezpieczającego
Projekt na Android Studio: DiceRollerFinal-challenge
Zasoby aplikacji
- Zasoby aplikacji mogą zawierać obrazy i ikony, standardowe kolory używane w aplikacji, ciągi tekstowe i układy XML. Wszystkie te zasoby są przechowywane w folderze
res
. - W folderze zasobów
drawable
umieść wszystkie zasoby graficzne w aplikacji.
Używanie elementów graficznych wektorowych w widokach obrazów:
- Rysunki wektorowe to obrazy opisane w formacie XML. Obrazy rysunkowe wektorowe są bardziej elastyczne niż obrazy bitmap (np. pliki PNG), ponieważ można je skalować do dowolnego rozmiaru i rozdzielczości.
- Aby dodać rysunek do układu aplikacji, użyj elementu
<ImageView>
. Źródło obrazu znajduje się w atrybucieandroid:src
. Aby odwołać się do folderu zasobów, które można rysować, użyj@drawable
, na przykład"@drawable/image_name"
. - Użyj widoku
ImageView
w kodzieMainActivity
obrazu. Za pomocąsetImageResource()
możesz zmienić obraz widoku na inny zasób. Używaj znacznikówR.drawable
do odwoływania się do określonych elementów rysowalnych, na przykładsetImageResource(R.drawable.image_name)
.
Słowo kluczowe lateinit
:
- Zminimalizuj wywołania funkcji
findViewById()
w kodzie, deklarując pola do przechowywania tych widoków i inicjując pola wonCreate()
. Użyj w tym polu słowa kluczowegolateinit
, aby uniknąć deklarowania jego wartości unieważniającej.
Przestrzeń nazw tools
dla atrybutów czas-projektu:
- Użyj atrybutu
tools:src
w elemencie<ImageView>
w układzie, aby wyświetlać obraz tylko w podglądzie lub edytorze projektu w Android Studio. Następnie możesz użyć pustego obrazu dla aplikacjiandroid:src
w ostatecznym interfejsie. - Użyj przestrzeni nazw
tools
w pliku układu Androida, by utworzyć zastępcze treści lub wskazówki dotyczące układu w Android Studio. Dane zadeklarowane przez atrybutytools
nie są używane w aplikacji końcowej.
Poziomy interfejsu API:
- Każdy system operacyjny Android ma oficjalną nazwę i wersję wersji (np. Android 9.0, &Pie") oraz poziom API (API 28). Użyj poziomów interfejsu API w plikach Gradle aplikacji, aby wskazać wersje Androida obsługiwane przez Twoją aplikację.
- Parametr
compileSdkVersion
w plikubuild.gradle
określa poziom interfejsu API Androida, którego Gradle ma używać do kompilowania aplikacji. - Parametr
targetSdkVersion
określa najnowszy poziom interfejsu API, na którym przetestowano aplikację. W wielu przypadkach ten parametr ma taką samą wartość jakcompileSdkVersion
. - Parametr
minSdkVersion
określa najstarszy poziom interfejsu API, na którym może działać Twoja aplikacja.
Jetpack dla Androida:
- Android Jetpack to zbiór bibliotek stworzonych przez Google. Można w nim znaleźć kursy zgodne z wcześniejszymi wersjami oraz przydatne funkcje obsługujące starsze wersje Androida. Jetpack zastępuje i rozszerza zestaw bibliotek nazywanych wcześniej Biblioteką pomocy Androida.
- Klasy zaimportowane z pakietu
androidx
odnoszą się do bibliotek Jetpack. Zależności Jetpacka z plikubuild.gradle
również zaczynają się odandroidx
.
Zgodność wsteczna z rysunkami wektorowymi:
- Rysunki wektorowe są obsługiwane natywnie tylko w wersjach Androida wyższych niż API 21. W starszych wersjach Gradle generuje obrazy PNG dla tych obiektów rysowanych podczas tworzenia aplikacji.
- Możesz określić, że Biblioteka pomocy Androida ma być używana w przypadku obiektów wektorowych w starszych wersjach interfejsu API z parametrem konfiguracji
vectorDrawables.useSupportLibrary = true
w plikubuild.gradle
. - Gdy włączysz bibliotekę pomocy dla obiektów rysowalnych wektorowych, użyj atrybutu
app:srcCompat
w elemencie<ImageView>
(zamiastandroid:src
), aby określić źródło rysowania wektorowego dla tego obrazu.
Przestrzeń nazw app
:
- Przestrzeń nazw
app
w pliku układu XML jest przeznaczona na atrybuty pochodzące z niestandardowego kodu lub z bibliotek, a nie z podstawowej platformy Android.
Kurs Udacity:
Dokumentacja dla programistów Androida:
ImageView
- Omówienie zasobów aplikacji
findViewById
()
- Informacje o atrybutach narzędzi
- Obsługa różnych wersji platformy
- Określanie wymagań na poziomie interfejsu API
- Jetpack na Androida
Inne:
Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:
- W razie potrzeby przypisz zadanie domowe.
- Poinformuj uczniów, jak przesyłać zadania domowe.
- Oceń projekty domowe.
Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.
Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.
Zmienianie aplikacji
W aplikacji DiceRoller dodaj przycisk Wyczyść, który ustawia obraz z powrotem na pusty obraz.
Odpowiedz na te pytania
Pytanie 1
Który atrybut <ImageView>
wskazuje obraz źródłowy, którego należy używać tylko w Android Studio?
android:srcCompat
app:src
tools:src
tools:sourceImage
Pytanie 2
Która metoda zmienia zasób graficzny ImageView
w kodzie Kotlin? xmx
setImageResource()
setImageURI()
setImage()
setImageRes()
Pytanie 3
Co oznacza słowo kluczowe lateinit
w deklaracji zmiennej w kotlinie?
- Zmienna nigdy nie jest inicjowana.
- Zmienna jest inicjowana tylko w czasie działania aplikacji.
- Zmienna jest automatycznie inicjowana w postaci
null
. - Zmienna zostanie zainicjowana później. Obiecuję.
Pytanie 4
Która konfiguracja Gradle wskazuje najnowszy poziom interfejsu API, na którym przetestowano aplikację?
minSdkVersion
compileSdkVersion
targetSdkVersion
testSdkVersion
Pytanie 5
W kodzie znajduje się wiersz importowania zaczynający się od androidx
. Co to oznacza?
- Klasa jest częścią bibliotek Android Jetpack.
- Klasa jest w bibliotece zewnętrznej, która będzie dynamicznie ładowana, gdy aplikacja zostanie uruchomiona.
- Klasa to „extra"” – opcjonalnie.
- Klasa jest częścią obsługi języka XML w Androidzie'.
Przesyłanie aplikacji do oceny
Upewnij się, że aplikacja zawiera:
- Układ aplikacji powinien zawierać jeden widok obrazu i dwa przyciski.
- Kod aplikacji powinien ustawić dwa moduły obsługi kliknięć – po jednym dla każdego przycisku.
- Moduł obsługi kliknięcia przycisku Wyczyść powinien ustawić obraz układu na
R.drawable.empty_dice
.
Rozpocznij następną lekcję:
Linki do innych ćwiczeń z programowania w tym kursie znajdziesz na stronie docelowej z ćwiczeniami z podstaw Androida Kotlin.