Ten moduł Codelab jest częścią kursu Android Kotlin Fundamentals. Najwięcej korzyści przyniesie Ci ukończenie wszystkich ćwiczeń w kolejności. Wszystkie ćwiczenia z tego kursu znajdziesz na stronie docelowej kursu Android Kotlin Fundamentals.
Wprowadzenie
Niezależnie od tego, czy tworzysz aplikację dla przyjemności, czy w celach biznesowych, warto zadbać o to, aby była ona użyteczna dla jak największej liczby użytkowników. Osiągnięcie tego celu ma wiele aspektów.
- Obsługa języków RTL W językach europejskich i wielu innych tekst czyta się od lewej do prawej, a aplikacje pochodzące z tych regionów są zwykle zaprojektowane tak, aby dobrze pasowały do tych języków. Wiele innych języków, którymi posługuje się duża liczba osób, czyta się od prawej do lewej, np. arabski. Zadbaj o to, aby Twoja aplikacja działała w językach zapisywanych od prawej do lewej, aby zwiększyć liczbę potencjalnych odbiorców.
- Skanowanie pod kątem ułatwień dostępu Próba zgadnięcia, jak inni użytkownicy mogą korzystać z Twojej aplikacji, wiąże się z pewnymi pułapkami. Aplikacja Accessibility Scanner analizuje aplikację i wskazuje miejsca, w których można poprawić ułatwienia dostępu.
- Projektuj z myślą o TalkBack, dodając opisy treści. Wady wzroku są bardziej powszechne, niż mogłoby się wydawać, a wielu użytkowników, nie tylko osoby niewidome, korzysta z czytnika ekranu. Opisy treści to frazy, które czytnik ekranu odczytuje, gdy użytkownik wchodzi w interakcję z elementem ekranu.
- Obsługa trybu nocnego Wielu użytkowników niedowidzących może poprawić kontrast, zmieniając kolory ekranu, co ułatwi im korzystanie z aplikacji. Android ułatwia obsługę trybu nocnego, dlatego zawsze warto go włączyć, aby zapewnić użytkownikom prostą alternatywę dla domyślnych kolorów ekranu.
W tym laboratorium kodowania poznasz każdą z tych opcji i dodasz jej obsługę do aplikacji GDG Finder.
Dowiesz się też, jak używać elementów w aplikacji na Androida. Możesz ich używać, aby uatrakcyjnić aplikację, zachowując przy tym jej dostępność.
Co warto wiedzieć
Musisz znać:
- Jak tworzyć aplikacje z aktywnościami i fragmentami oraz jak poruszać się między fragmentami, przekazując dane.
- Używanie widoków i grup widoków do tworzenia interfejsu, w szczególności RecyclerView.
- Jak używać komponentów architektury, w tym
ViewModel
, z zalecaną architekturą do tworzenia dobrze zorganizowanych i wydajnych aplikacji. - Wiązanie danych, współprogramy i obsługa kliknięć myszą.
- Jak połączyć się z internetem i lokalnie buforować dane za pomocą bazy danych Room.
- Jak ustawiać właściwości widoku oraz jak wyodrębniać zasoby do plików zasobów XML i z nich korzystać.
- Jak używać stylów i motywów do dostosowywania wyglądu aplikacji.
- Jak korzystać z komponentów Material, zasobów wymiarów i niestandardowego kolorowania.
Czego się nauczysz
- Jak sprawić, by z Twojej aplikacji mogło korzystać jak najwięcej osób.
- Jak dostosować aplikację do języków zapisywanych od prawej do lewej.
- Jak ocenić ułatwienia dostępu w aplikacji.
- Jak używać opisów treści, aby aplikacja lepiej współpracowała z czytnikami ekranu.
- Jak korzystać z elementów.
- Jak dostosować aplikację do trybu ciemnego.
Jakie zadania wykonasz
- Oceniaj i rozszerzaj daną aplikację, aby zwiększyć jej dostępność, dostosowując ją do języków zapisywanych od prawej do lewej.
- Skanuj aplikację, aby określić, gdzie można poprawić ułatwienia dostępu.
- Używaj opisów treści w przypadku obrazów.
- Dowiedz się, jak korzystać z elementów rysowalnych.
- Dodaj do aplikacji możliwość korzystania z trybu nocnego.
Aplikacja startowa GDG-finder wykorzystuje wszystko, czego do tej pory nauczyłeś się w tym kursie.
Aplikacja używa ConstraintLayout
do wyświetlania 3 ekranów. Dwa z nich to tylko pliki układu, które posłużą Ci do poznania kolorów i tekstu na Androidzie.
Trzeci ekran to wyszukiwarka GDG. GDG, czyli Google Developer Groups, to społeczności deweloperów, które koncentrują się na technologiach Google, w tym na Androidzie. Grupy GDG na całym świecie organizują spotkania, konferencje, maratony szkoleniowe i inne wydarzenia.
Podczas tworzenia tej aplikacji pracujesz nad prawdziwą listą GDG. Ekran wyszukiwarki korzysta z lokalizacji urządzenia, aby sortować GDG według odległości.
Jeśli masz szczęście i w Twoim regionie działa GDG, możesz odwiedzić stronę internetową tej grupy i zarejestrować się na jej wydarzenia. Wydarzenia GDG to świetny sposób na poznanie innych deweloperów Androida i nauczenie się sprawdzonych metod, które nie zmieściły się w tym kursie.
Zrzuty ekranu poniżej pokazują, jak aplikacja będzie się zmieniać od początku do końca tego ćwiczenia.
Główna różnica między językami zapisanymi od lewej do prawej (LTR) a językami zapisanymi od prawej do lewej (RTL) polega na kierunku wyświetlania treści. Gdy kierunek interfejsu użytkownika zmieni się z od lewej do prawej na od prawej do lewej (lub odwrotnie), często nazywa się to powielaniem. Odbicie lustrzane obejmuje większość ekranu, w tym tekst, ikony pól tekstowych, układy i ikony z kierunkami (np. strzałki). Inne elementy nie są odzwierciedlane, np. liczby (zegar, numery telefonów), ikony, które nie mają kierunku (tryb samolotowy, Wi-Fi), elementy sterujące odtwarzaniem oraz większość wykresów.
Języki, w których tekst jest pisany od prawej do lewej, są używane przez ponad miliard osób na całym świecie. Deweloperzy Androida są na całym świecie, więc aplikacja GDG Finder musi obsługiwać języki pisane od prawej do lewej.
Krok 1. Dodaj obsługę języków pisanych od prawej do lewej
W tym kroku sprawisz, że aplikacja GDG Finder będzie działać w językach zapisywanych od prawej do lewej.
- Pobierz i uruchom aplikację GDGFinderMaterial, która jest aplikacją początkową w tym ćwiczeniu, lub kontynuuj pracę z kodem końcowym z poprzedniego ćwiczenia.
- Otwórz plik Android Manifest.
- W sekcji
<application>
dodaj ten kod, aby określić, że aplikacja obsługuje pisanie od prawej do lewej.
<application
...
android:supportsRtl="true">
- Otwórz plik activity_main.xml na karcie Projekt.
- W menu Język podglądu wybierz Podgląd od prawej do lewej. (Jeśli nie widzisz tego menu, rozszerz panel lub zamknij panel Atrybuty, aby go odkryć).
- W sekcji Podgląd zauważ, że nagłówek „Wyszukiwarka GDG” został przesunięty w prawo, a reszta ekranu pozostała w zasadzie bez zmian. Ogólnie ten ekran jest akceptowalny. Wyrównanie w widoku tekstowym jest teraz nieprawidłowe, ponieważ tekst jest wyrównany do lewej, a nie do prawej.
- Aby to zadziałało na urządzeniu, w Ustawieniach urządzenia lub emulatora w Opcjach programisty wybierz Wymuś układ od prawej do lewej. (Jeśli musisz włączyć Opcje programisty, znajdź Numer kompilacji i klikaj go, aż pojawi się komunikat informujący o tym, że jesteś programistą. Zależy to od urządzenia i wersji systemu Android).
- Uruchom aplikację i sprawdź na urządzeniu, czy ekran główny wygląda tak samo jak w podglądzie. Zwróć uwagę, że przycisk FAB został przeniesiony na lewą stronę, a menu z 3 kreskami na prawą.
- W aplikacji otwórz panel nawigacji i przejdź do ekranu Szukaj. Jak widać poniżej, ikony nadal znajdują się po lewej stronie i nie widać żadnego tekstu. Okazuje się, że tekst znajduje się poza ekranem, po lewej stronie ikony. Jest to spowodowane tym, że kod używa odniesień do lewej i prawej strony ekranu we właściwościach widoku i ograniczeniach układu.
Krok 2. Zamiast lewej i prawej używaj początku i końca
„Lewa” i „prawa” strona ekranu (gdy patrzysz na ekran) nie zmieniają się, nawet jeśli kierunek tekstu ulegnie zmianie. Na przykład layout_constraintLeft_toLeftOf
zawsze ogranicza lewą stronę elementu do lewej strony ekranu. W przypadku Twojej aplikacji tekst w językach zapisywanych od prawej do lewej jest poza ekranem, jak widać na zrzucie ekranu powyżej.
Aby to naprawić, zamiast „lewy” i „prawy” używaj terminologii Start
i End
. Ta terminologia określa początek i koniec tekstu odpowiednio do kierunku tekstu w bieżącym języku, dzięki czemu marginesy i układy znajdują się we właściwych obszarach ekranów.
Open
list_item.xml- Zastąp wszystkie odwołania do
Left
iRight
odwołaniami doStart
iEnd
.
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
- Zastąp
layout_marginLeft
użytkownikaImageView
tekstemlayout_marginStart
. Spowoduje to przesunięcie marginesu w odpowiednie miejsce, aby odsunąć ikonę od krawędzi ekranu.
<ImageView
android:layout_marginStart="
?
- Otwórz pokój
fragment_gdg_list.xml
. Sprawdź listę GDG w panelu Podgląd. Zwróć uwagę, że ikona nadal jest skierowana w niewłaściwym kierunku, ponieważ jest odwrócona (jeśli ikona nie jest odwrócona, upewnij się, że nadal wyświetlasz podgląd od prawej do lewej). Zgodnie z wytycznymi Material Design ikony nie powinny być odwracane. - Otwórz plik res/drawable/ic_gdg.xml.
- W pierwszym wierszu kodu XML znajdź i usuń znak
android:autoMirrored="true"
, aby wyłączyć dublowanie. - Sprawdź podgląd lub ponownie uruchom aplikację i otwórz ekran wyszukiwania GDG. Układ powinien być teraz prawidłowy.
Krok 3. Pozwól Androidowi Studio wykonać pracę za Ciebie
W poprzednim ćwiczeniu wykonaliśmy pierwsze kroki w celu obsługi języków zapisywanych od prawej do lewej. Na szczęście Android Studio może przeskanować Twoją aplikację i skonfigurować wiele podstawowych elementów.
- W pliku list_item.xml w elemencie
TextView
zmieńlayout_marginStart
z powrotem nalayout_marginLeft
, aby skaner miał coś do znalezienia.
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
- W Android Studio wybierz Refactor > Add RTL support where possible (Refaktoryzacja > Dodaj obsługę języków pisanych od prawej do lewej, jeśli to możliwe) i zaznacz pola wyboru, aby zaktualizować plik manifestu i pliki układu, tak aby używały właściwości start i end.
- W panelu Podgląd refaktoryzacji znajdź folder app i rozwiń go, aby wyświetlić wszystkie szczegóły.
- W folderze aplikacji zauważ, że plik
layout_marginLeft
, który właśnie został zmieniony, jest wymieniony jako kod do refaktoryzacji.
- Zwróć uwagę, że w podglądzie są też wymienione pliki systemowe i pliki biblioteki. Kliknij prawym przyciskiem myszy foldery layout i layout-watch-v20 oraz inne foldery, które nie należą do folderu app, i z menu kontekstowego wybierz Wyklucz.
- Przeprowadź refaktoryzację już teraz. (Jeśli pojawi się wyskakujące okienko dotyczące plików systemowych, upewnij się, że wykluczasz wszystkie foldery, które nie są częścią kodu aplikacji).
- Zwróć uwagę, że pole
layout_marginLeft
zostało zmienione z powrotem nalayout_marginStart
.
Krok 3. Przejrzyj foldery dla poszczególnych ustawień regionalnych
Do tej pory zmieniliśmy tylko kierunek domyślnego języka używanego w aplikacji. W przypadku aplikacji produkcyjnej wysyłasz plik strings.xml do tłumacza, aby przetłumaczył go na nowy język. W tym laboratorium kodowania aplikacja udostępnia plik strings.xml w języku hiszpańskim (do wygenerowania tłumaczeń użyliśmy Tłumacza Google, więc nie są one idealne).
- W Android Studio przełącz widok projektu na Pliki projektu.
- Rozwiń folder res. Zobaczysz foldery res/values i res/values-es. Ciąg „es” w nazwie folderu to kod języka hiszpańskiego. Foldery values-"language code" zawierają wartości dla każdego obsługiwanego języka. Folder values bez rozszerzenia zawiera domyślne zasoby, które są stosowane w innych przypadkach.
- W folderze values-es otwórz plik strings.xml. Zobaczysz, że wszystkie ciągi znaków są w języku hiszpańskim.
- W Android Studio otwórz
activity_main.xml
na karcie Projekt. - W menu Język podglądu wybierz Hiszpański. Tekst powinien być teraz w języku hiszpańskim.
- [Opcjonalnie] Jeśli dobrze znasz język zapisywany od prawej do lewej, utwórz folder values i plik strings.xml w tym języku i sprawdź, jak wyświetlają się na urządzeniu.
- [Opcjonalnie] Zmień ustawienia języka na urządzeniu i uruchom aplikację. Nie zmieniaj języka urządzenia na taki, którego nie znasz, ponieważ może to utrudnić cofnięcie zmian.
W poprzednim zadaniu ręcznie zmieniliśmy aplikację, a potem użyliśmy Android Studio, aby sprawdzić, czy można wprowadzić dodatkowe ulepszenia związane z obsługą języków pisanych od prawej do lewej.
Aplikacja Accessibility Scanner to najlepsze narzędzie, które pomoże Ci zadbać o dostępność aplikacji. Skanuje ona aplikację na urządzeniu docelowym i sugeruje ulepszenia, np. powiększenie obszarów dotyku, zwiększenie kontrastu i dodanie opisów obrazów, aby ułatwić korzystanie z aplikacji. Accessibility Scanner to aplikacja stworzona przez Google, którą możesz zainstalować ze Sklepu Play.
Krok 1. Zainstaluj i uruchom Accessibility Scanner
- Otwórz Sklep Play i w razie potrzeby zaloguj się. Możesz to zrobić na urządzeniu fizycznym lub w emulatorze. W tym laboratorium używamy emulatora.
- W Sklepie Play wyszukaj Accessibility Scanner od Google LLC. Upewnij się, że pobierasz właściwą aplikację wydaną przez Google, ponieważ skanowanie wymaga wielu uprawnień.
- Zainstaluj skaner na emulatorze.
- Po zainstalowaniu kliknij Otwórz.
- Kliknij Rozpocznij.
- Kliknij OK, aby rozpocząć konfigurację aplikacji Accessibility Scanner w Ustawieniach.
- Kliknij Accessibility Scanner, aby otworzyć ustawienia Ułatwienia dostępu na urządzeniu.
- Aby włączyć usługę, kliknij Użyj usługi.
- Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie i przyznaj wszystkie uprawnienia.
- Następnie kliknij OK i wróć do ekranu głównego. Na ekranie może pojawić się niebieski przycisk z ikona potwierdzenia. Kliknięcie tego przycisku powoduje przetestowanie aplikacji na pierwszym planie. Możesz zmienić położenie przycisku, przeciągając go. Ten przycisk jest zawsze na wierzchu innych aplikacji, więc możesz w każdej chwili rozpocząć testowanie.
- Otwórz lub uruchom aplikację.
- Kliknij niebieski przycisk i zaakceptuj dodatkowe ostrzeżenia dotyczące bezpieczeństwa oraz uprawnienia.
Gdy po raz pierwszy klikniesz ikonę Skanera ułatwień dostępu, aplikacja poprosi o zezwolenie na dostęp do wszystkiego, co jest wyświetlane na ekranie. To uprawnienie może budzić obawy i tak jest w rzeczywistości.
Niemal nigdy nie należy przyznawać takich uprawnień, ponieważ umożliwiają one aplikacjom odczytywanie e-maili, a nawet pobieranie informacji o koncie bankowym. Aby jednak Accessibility Scanner mógł działać, musi sprawdzać aplikację w taki sam sposób jak użytkownik – dlatego potrzebuje tych uprawnień.
- Kliknij niebieski przycisk i poczekaj na zakończenie analizy. Zobaczysz ekran podobny do tego poniżej, z tytułem i przyciskiem FAB w czerwonej ramce. Oznacza to, że na tym ekranie są 2 sugestie dotyczące ułatwień dostępu.
- Kliknij pole otaczające GDG Finder. Otworzy się panel z dodatkowymi informacjami, jak pokazano poniżej, wskazujący problemy z kontrastem obrazu.
- Rozwiń informacje o kontraście obrazu, a narzędzie zaproponuje rozwiązania.
- Aby uzyskać informacje o kolejnym elemencie, kliknij strzałki po prawej stronie.
- W aplikacji otwórz ekran Zgłoś się do GDG i zeskanuj go za pomocą aplikacji Accessibility Scanner. Wyświetli ona kilka sugestii, jak pokazano poniżej po lewej stronie. Dokładnie 12. Niektóre z nich są duplikatami podobnych produktów.
- Kliknij ikonę „stos”
na dolnym pasku narzędzi, aby wyświetlić listę wszystkich sugestii, jak pokazano poniżej na zrzucie ekranu po prawej stronie. W tym laboratorium kodu zajmiemy się wszystkimi tymi problemami.
Pakiet ułatwień dostępu na Androida to zbiór aplikacji Google, które pomagają zwiększyć dostępność aplikacji. Obejmuje ona narzędzia takie jak TalkBack. TalkBack to czytnik ekranu, który zapewnia informacje zwrotne w postaci dźwięków, wibracji i komunikatów głosowych. Umożliwia użytkownikom poruszanie się po urządzeniach i korzystanie z treści bez patrzenia na ekran.
Okazuje się, że z TalkBack korzystają nie tylko osoby niewidome, ale też wiele osób z różnego rodzaju wadami wzroku. A nawet osoby, które po prostu chcą odpocząć od patrzenia na ekran.
Ułatwienia dostępu są więc dla wszystkich. W tym zadaniu wypróbujesz TalkBack i zaktualizujesz aplikację, aby dobrze z nią współpracowała.
Krok 1. Zainstaluj i uruchom pakiet Accessibility Suite
TalkBack jest wstępnie zainstalowany na wielu urządzeniach fizycznych, ale na emulatorze musisz go zainstalować.
- Otwórz Sklep Play.
- Znajdź pakiet ułatwień dostępu. Sprawdź, czy jest to właściwa aplikacja od Google.
- Jeśli nie jest zainstalowany, zainstaluj pakiet ułatwień dostępu.
- Aby włączyć TalkBack na urządzeniu, otwórz Ustawienia > Ułatwienia dostępu i włącz TalkBack, wybierając Użyj usługi. Podobnie jak skaner ułatwień dostępu, TalkBack wymaga uprawnień do odczytywania treści na ekranie. Gdy zaakceptujesz prośby o uprawnienia, TalkBack wyświetli listę samouczków, które pomogą Ci efektywnie korzystać z tej funkcji.
- Zatrzymaj się w tym miejscu i przejdź samouczki, choćby po to, aby dowiedzieć się, jak wyłączyć TalkBack, gdy skończysz.
- Aby zamknąć samouczek, kliknij przycisk Wstecz, a następnie kliknij dwukrotnie dowolne miejsce na ekranie.
- Dowiedz się, jak korzystać z aplikacji GDG Finder z TalkBack. Zwróć uwagę na miejsca, w których TalkBack nie podaje przydatnych informacji o ekranie lub elemencie sterującym. Naprawisz to w następnym ćwiczeniu.
Krok 2. Dodaj opis treści
Deskryptory treści to etykiety opisowe, które wyjaśniają znaczenie wyświetleń. Większość widoków powinna zawierać opisy treści.
- Uruchom aplikację GDG Finder i włącz TalkBack. Następnie przejdź do ekranu Zgłoś chęć prowadzenia GDG.
- Klikam obraz główny… i nic się nie dzieje.
- Otwórz plik add_gdg_fragment.xml.
- W polu
ImageView
dodaj atrybut deskryptora treści, jak pokazano poniżej. Ciągstage_image_description
jest dostępny w pliku strings.xml.
android:contentDescription="@string/stage_image_description"
- Uruchom aplikację.
- Kliknij obraz w sekcji Zgłoś chęć prowadzenia GDG. Powinien być teraz słyszalny krótki opis obrazu.
- [Opcjonalnie] Dodaj opisy treści do pozostałych obrazów w tej aplikacji. W aplikacji produkcyjnej wszystkie obrazy muszą mieć opisy treści.
Krok 3. Dodaj podpowiedzi do pól tekstowych z możliwością edycji
W przypadku elementów, które można edytować, np. EditText
, możesz użyć elementu android:hint
w pliku XML, aby pomóc użytkownikom w określeniu, co mają wpisać. Wskazówka jest zawsze widoczna w interfejsie, ponieważ jest domyślnym tekstem w polu wprowadzania.
- Nadal w pliku add_gdg_fragment.xml.
- Dodaj opisy i wskazówki dotyczące treści, korzystając z poniższego kodu jako przewodnika.
Dodaj do: textViewIntro
android:contentDescription="@string/add_gdg"
Dodaj do pól edycji tekstu odpowiednio:
android:hint="@string/your_name_label"
android:hint="@string/email_label"
android:hint="@string/city_label"
android:hint="@string/country_label"
android:hint="@string/region_label"
- Dodaj opis treści do
labelTextWhy
.
android:contentDescription="@string/motivation"
- Dodaj podpowiedź do
EditTextWhy
. Po oznaczeniu pól edycji dodaj do etykiety opis treści, a także wskazówkę do pola.
android:hint="@string/enter_motivation"
- Dodaj opis treści przycisku przesyłania. Wszystkie przyciski muszą mieć opis tego, co się stanie po ich naciśnięciu.
android:contentDescription="@string/submit_button_description"
- Uruchom aplikację z włączoną funkcją TalkBack i wypełnij formularz, aby zgłosić się do prowadzenia GDG.
Krok 4. Utwórz grupę treści
W przypadku elementów interfejsu, które TalkBack powinien traktować jako grupę, możesz użyć grupowania treści. Powiązane treści, które są zgrupowane, są odczytywane razem. Użytkownicy technologii wspomagających nie będą musieli tak często przesuwać palcem po ekranie, skanować go ani czekać, aby odkryć wszystkie informacje na ekranie. Nie ma to wpływu na wygląd elementów sterujących na ekranie.
Aby zgrupować komponenty interfejsu, umieść je w elemencie ViewGroup
, np. w elemencie LinearLayout
. W aplikacji GDG Finder elementy labelTextWhy
i editTextWhy
doskonale nadają się do grupowania, ponieważ są ze sobą powiązane semantycznie.
- Otwórz plik add_gdg_fragment.xml.
- Umieść
LinearLayout
wokółLabelTextWhy
iEditTextWhy
, aby utworzyć grupę treści. Skopiuj i wklej poniższy kod. TenLinearLayout
zawiera już niektóre style, których potrzebujesz. (Upewnij się, że symbolbutton
znajduje się POZA symbolemLinearLayout
).
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
android:layout_height="wrap_content" android:focusable="true"
app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
android:layout_marginBottom="8dp">
<!-- label and edit text here –>
<LinearLayout/>
- Wybierz Code > Reformat code (Kod > Zmień format kodu), aby prawidłowo wciąć cały kod.
- Usuń wszystkie marginesy układu z urządzeń
labelTextWhy
ieditTextWhy
. - W polu
labelTextWhy
zmień ograniczenielayout_constraintTop_toTopOf
nacontentGroup
.
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
- W polu
editTextWhy
zmień ograniczenielayout_constraintBottom_toBottomOf
nacontentGroup
.
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
- Ogranicz
EditTextRegion
iButton
docontentGroup
, aby usunąć błędy.
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
- Dodaj marginesy do elementu
LinearLayout
. Opcjonalnie możesz wyodrębnić ten margines jako wymiar.
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
Jeśli potrzebujesz pomocy, porównaj swój kod z add_gdg_fragment.xml
w kodzie rozwiązania.
- Uruchom aplikację i przejdź do ekranu Zgłoś chęć prowadzenia GDG za pomocą TalkBack.
Krok 5. Dodaj region na żywo
Obecnie przycisk przesyłania ma etykietę OK. Lepiej, aby przycisk miał jedną etykietę i opis przed przesłaniem formularza, a po kliknięciu przez użytkownika i przesłaniu formularza dynamicznie zmieniał etykietę i opis treści. Możesz to zrobić za pomocą regionu na żywo.
Aktywny region informuje usługi ułatwień dostępu, czy użytkownik powinien być powiadamiany o zmianach widoku. Na przykład informowanie użytkownika o nieprawidłowym haśle lub błędzie sieci to świetny sposób na zwiększenie dostępności aplikacji. W tym przykładzie, aby uprościć sprawę, informujesz użytkownika, kiedy przycisk przesyłania zmienia stan.
- Otwórz plik add_gdg_fragment.xml.
- Zmień przypisanie tekstu przycisku na Prześlij, używając podanego zasobu ciągu znaków
submit
.
android:text="@string/submit"
- Dodaj do przycisku obszar aktywny, ustawiając atrybut
android:accessibilityLiveRegion
. Podczas wpisywania wartości masz do wyboru kilka opcji. W zależności od wagi zmiany możesz zdecydować, czy chcesz przerwać użytkownikowi pracę. W przypadku wartości „assertive” usługi ułatwień dostępu przerywają bieżącą mowę, aby natychmiast ogłosić zmiany w tym widoku. Jeśli ustawisz wartość „none”, żadne zmiany nie będą ogłaszane. Jeśli ustawisz wartość „polite”, usługi ułatwień dostępu będą ogłaszać zmiany, ale poczekają na swoją kolej. Ustaw wartość „polite”.
android:accessibilityLiveRegion="polite"
- W pakiecie add otwórz plik AddGdgFragment.kt.
- W
showSnackBarEvent
Observer
po zakończeniu wyświetlaniaSnackBar
ustaw nowy opis treści i tekst przycisku.
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
- Uruchom aplikację i kliknij przycisk. Niestety przycisk i czcionka są za małe.
Krok 6. Popraw styl przycisku
- W pliku add_gdg_fragment.xml zmień wartości atrybutów
width
iheight
przycisku nawrap_content
, aby wyświetlała się pełna etykieta, a przycisk miał odpowiedni rozmiar.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- Usuń atrybuty
backgroundTint
,textColor
itextSize
z przycisku, aby aplikacja używała lepszego stylu motywu. - Usuń atrybut
textColor
ztextViewIntro
. Kolory motywu powinny zapewniać dobry kontrast. - Uruchom aplikację. Zwróć uwagę na znacznie bardziej użyteczny przycisk Prześlij. Kliknij Prześlij i zobacz, jak zmienia się na Gotowe.
Elementy to niewielkie elementy reprezentujące atrybut, tekst, podmiot lub działanie. Umożliwiają użytkownikom wprowadzanie informacji, wybieranie opcji, filtrowanie treści lub wywoływanie działania.
Chip
to cienki widżet opakowujący ChipDrawable
, który zawiera całą logikę układu i rysowania. Dodatkowa logika obsługuje nawigację za pomocą dotyku, myszy, klawiatury i ułatwień dostępu. Główny element i ikona zamknięcia są traktowane jako oddzielne logiczne widoki podrzędne i mają własne zachowanie nawigacyjne oraz stan.
Elementy korzystają z zasobów rysowalnych. Obiekty rysowalne w Androidzie umożliwiają rysowanie na ekranie obrazów, kształtów i animacji. Mogą mieć stały rozmiar lub być dynamicznie dopasowywane. Możesz używać obrazów jako elementów rysowalnych, np. obrazów w aplikacji GDG. Możesz też używać rysunków wektorowych, aby narysować wszystko, co tylko sobie wyobrazisz. Istnieje też obraz z możliwością zmiany rozmiaru, zwany obrazem 9-patch, który nie jest omawiany w tym ćwiczeniu z programowania. Logo GDG w pliku drawable/ic_gdg.xml to kolejny element rysowalny.
Obiekty rysowalne nie są widokami, więc nie można ich umieścić bezpośrednio w elemencie ConstraintLayout
. Musisz umieścić je w elemencie ImageView
. Możesz też używać zasobów rysowalnych jako tła widoku tekstu lub przycisku. Tło będzie rysowane za tekstem.
Krok 1. Dodaj elementy do listy GDG
Poniższy zaznaczony element używa 3 elementów rysowalnych. Tło i znacznik wyboru są rysunkami. Dotknięcie elementu powoduje efekt fali, który jest tworzony za pomocą specjalnego elementu RippleDrawable, który wyświetla efekt fali w odpowiedzi na zmiany stanu.
W tym zadaniu dodasz do listy GDG elementy, które będą zmieniać stan po wybraniu. W tym ćwiczeniu dodasz u góry ekranu Wyszukiwanie wiersz przycisków o nazwie chips. Każdy przycisk filtruje listę GDG, aby użytkownik otrzymywał tylko wyniki z wybranego regionu. Gdy przycisk zostanie wybrany, zmieni się jego tło i pojawi się na nim znacznik wyboru.
- Otwórz plik fragment_gdg_list.xml.
- Utwórz element
com.google.android.material.chip.ChipGroup
w elemencieHorizontalScrollView.
. Ustaw jego właściwośćsingleLine
natrue
, aby wszystkie elementy były ułożone w jednym wierszu z możliwością przewijania w poziomie. Ustaw właściwośćsingleSelection
natrue
, aby w danej chwili można było wybrać tylko jeden element w grupie. Oto kod.
<com.google.android.material.chip.ChipGroup
android:id="@+id/region_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
android:padding="@dimen/spacing_normal"/>
- W folderze layout utwórz nowy plik zasobu układu o nazwie region.xml, aby zdefiniować układ jednego elementu
Chip
. - W pliku region.xml zastąp cały kod układem jednego
Chip
, jak podano poniżej. Zwróć uwagę, żeChip
jest komponentem Material. Zwróć też uwagę, że znacznik wyboru pojawia się po ustawieniu właściwościapp:checkedIconVisible
. Pojawi się błąd dotyczący brakującego koloruselected_highlight
.
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Chip.Choice"
app:chipBackgroundColor="@color/selected_highlight"
app:checkedIconVisible="true"
tools:checked="true"/>
- Aby utworzyć brakujący kolor
selected_highlight
, umieść kursor na kolorzeselected_highlight
, otwórz menu intencji i utwórz zasób koloru dla wybranego wyróżnienia. Opcje domyślne są odpowiednie, więc kliknij OK. Plik zostanie utworzony w folderze res/color. - Otwórz plik res/color/selected_highlight.xml. Na tej liście stanów kolorów, zakodowanej jako
<selector>
, możesz podać różne kolory dla różnych stanów. Każdy stan i powiązany z nim kolor są zakodowane jako<item>
. Więcej informacji o tych kolorach znajdziesz w artykule Motywy kolorystyczne.
- Wewnątrz
<selector>
dodaj do listy stanów element z domyślnym koloremcolorOnSurface
. Na listach stanów ważne jest, aby zawsze uwzględniać wszystkie stany. Jednym ze sposobów na to jest ustawienie domyślnego koloru.
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
- Nad domyślnym kolorem dodaj
item
w kolorzecolorPrimaryVariant
i ogranicz jego użycie do sytuacji, gdy wybrany stan totrue
. Listy stanów są przetwarzane od góry do dołu, podobnie jak instrukcja case. Jeśli żaden stan nie pasuje, stosowany jest stan domyślny.
<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" />
Krok 2. Wyświetl wiersz z elementami
Aplikacja GDG tworzy listę elementów z regionami, w których działają grupy GDG. Gdy wybierzesz kartę, aplikacja przefiltruje wyniki, aby wyświetlać tylko wyniki GDG z danego regionu.
- W pakiecie search otwórz plik GdgListFragment.kt.
- W
onCreateView()
, tuż nad instrukcjąreturn
, dodaj obserwatora wviewModel.regionList
i zastąponChanged()
. Gdy lista regionów podana przez model widoku ulegnie zmianie, należy ponownie utworzyć komponenty. Dodaj instrukcję, aby natychmiast zwrócić wartość, jeśli podany argumentdata
tonull
.
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
override fun onChanged(data: List<String>?) {
data ?: return
}
})
- Wewnątrz
onChanged()
, poniżej testu wartości null, przypiszbinding.regionList
do nowej zmiennej o nazwiechipGroup
, aby zapisać w pamięci podręcznej wartośćregionList
.
val chipGroup = binding.regionList
- Poniżej utwórz nowy
layoutInflator
do nadmuchiwania chipsów zchipGroup.context
.
val inflator = LayoutInflater.from(chipGroup.context)
- Wyczyść i ponownie skompiluj projekt, aby pozbyć się błędu powiązania danych.
Pod inflatorem możesz teraz utworzyć rzeczywiste elementy, po jednym dla każdego regionu w regionList
.
- Utwórz zmienną
children
, która będzie przechowywać wszystkie elementy. Przypisz do niego funkcję mapowania w przekazanym argumenciedata
, aby utworzyć i zwrócić każdy element.
val children = data.map {}
- W funkcji lambda mapy dla każdego elementu
regionName
utwórz i rozwiń element. Gotowy kod znajdziesz poniżej.
val children = data.map {
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
// TODO: Click listener goes here.
chip
}
}
- W funkcji lambda, tuż przed zwróceniem wartości
chip
, dodaj detektor kliknięć. Gdy kliknieszchip
, ustaw stanchecked
. Wywołaj funkcjęonFilterChanged()
wviewModel
, co spowoduje wywołanie sekwencji zdarzeń, które pobiorą wynik dla tego filtra.
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
- Na końcu lambdy usuń wszystkie bieżące widoki z
chipGroup
, a następnie dodaj wszystkie elementy zchildren
dochipGroup
. (Nie możesz zaktualizować elementów, więc musisz usunąć i ponownie utworzyć zawartośćchipGroup
).
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
Ukończony obserwator powinien wyglądać tak:
override fun onChanged(data: List<String>?) {
data ?: return
val chipGroup = binding.regionList
val inflator = LayoutInflater.from(chipGroup.context)
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
chip
}
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
}
})
- Uruchom aplikację i wyszukaj GDGS, aby otworzyć ekran Wyszukiwanie i użyć nowych elementów. Po kliknięciu każdego elementu aplikacja wyświetli poniżej grupy filtrów.
Tryb nocny umożliwia aplikacji zmianę kolorów na ciemny motyw, na przykład gdy w ustawieniach urządzenia włączono tryb nocny. W trybie nocnym aplikacje zmieniają domyślne jasne tło na ciemne i odpowiednio dostosowują wszystkie inne elementy ekranu.
Krok 1. Włącz tryb nocny
Aby udostępnić ciemny motyw aplikacji, zmień jej motyw z Light
na DayNight
. Motyw DayNight
jest wyświetlany w jasnych lub ciemnych kolorach w zależności od trybu.
- W
styles.xml,
zmień motyw nadrzędnyAppTheme
zLight
naDayNight
.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
- W metodzie
MainActivity
onCreate()
wywołajAppCompatDelegate.setDefaultNightMode()
, aby programowo włączyć ciemny motyw.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
- Uruchom aplikację i sprawdź, czy przełączyła się na ciemny motyw.
Krok 2. Wygeneruj własną paletę kolorów motywu ciemnego
Aby dostosować ciemny motyw, utwórz foldery z kwalifikatorem -night
, którego będzie używać ciemny motyw. Możesz na przykład ustawić konkretne kolory w trybie nocnym, tworząc folder o nazwie values-night
.
- Otwórz selektor kolorów na stronie material.io i utwórz paletę kolorów motywu nocnego. Możesz na przykład użyć ciemnoniebieskiego.
- Wygeneruj i pobierz plik colors.xml.
- Przełącz się na widok Pliki projektu, aby wyświetlić listę wszystkich folderów w projekcie.
- Znajdź folder res i go rozwiń.
- Utwórz folder zasobów res/values-night.
- Dodaj nowy plik colors.xml do folderu zasobów res/values-night.
- Uruchom aplikację z włączonym trybem nocnym. Powinna ona używać nowych kolorów zdefiniowanych w folderze res/values-night. Zwróć uwagę, że w elementach użyto nowego koloru dodatkowego.
Projekt Android Studio: GDGFinderFinal.
Obsługa języków RTL
- W pliku manifestu Androida ustaw wartość
android:supportsRtl="true"
. - Możesz wyświetlić podgląd tekstu zapisanego od prawej do lewej w emulatorze i sprawdzić układ ekranu w swoim języku. Na urządzeniu lub emulatorze otwórz Ustawienia, a w Opcjach programisty wybierz Wymuś układ od prawej do lewej.
- Zastąp odwołania do
Left
iRight
odwołaniami doStart
iEnd
. - Wyłącz dublowanie elementów rysowalnych, usuwając
android:autoMirrored="true"
. - Wybierz Refactor > Add RTL support where possible (Refaktoryzuj > Dodaj obsługę języków pisanych od prawej do lewej, jeśli to możliwe), aby Android Studio wykonało to za Ciebie.
- Używaj folderów values-"language code" do przechowywania zasobów w określonym języku.
Skanowanie pod kątem ułatwień dostępu
- W Sklepie Play pobierz aplikację Accessibility Scanner od Google LLC i uruchom ją, aby przeskanować elementy ekranu, które można ulepszyć.
Projektowanie z myślą o TalkBack z opisami treści
- Zainstaluj Pakiet ułatwień dostępu na Androida od Google, który zawiera TalkBack.
- Dodaj opisy treści do wszystkich elementów interfejsu. Na przykład:
android:contentDescription="@string/stage_image_description"
- W przypadku elementu, który można edytować, np.
EditText
, użyj atrybutuandroid:hint
w pliku XML, aby podać użytkownikowi wskazówkę dotyczącą tego, co ma wpisać. - Twórz grupy treści, umieszczając powiązane elementy w grupie widoku.
- Utwórz region na żywo, aby przekazywać użytkownikom dodatkowe informacje zwrotne za pomocą
android:accessibilityLiveRegion
.
Używanie elementów do implementowania filtra
- Elementy to drobne elementy reprezentujące atrybut, tekst, encję lub działanie.
- Aby utworzyć grupę elementów, użyj znaku
com.google.android.material.chip.ChipGroup
. - Określ układ dla 1 atrybutu
com.google.android.material.chip.Chip
. - Jeśli chcesz, aby elementy zmieniały kolor, podaj listę stanów kolorów jako
<selector>
z kolorami zależnymi od stanu:<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" /> - Powiąż elementy z danymi na żywo, dodając obserwatora do danych w modelu widoku.
- Aby wyświetlić elementy, utwórz inflator dla grupy elementów:
LayoutInflater.from(chipGroup.context)
- Utwórz elementy, dodaj odbiornik kliknięć, który wywołuje żądane działanie, i dodaj elementy do grupy elementów.
Obsługa trybu ciemnego
- Użyj
DayNight
AppTheme
, aby obsługiwać tryb ciemny. - Tryb ciemny możesz ustawić programowo:
AppCompatDelegate.setDefaultNightMode()
- Utwórz folder zasobów res/values-night, aby udostępniać niestandardowe kolory i wartości dla trybu ciemnego.
Dokumentacja dla deweloperów aplikacji na Androida:
LayoutDirection
(RTL)- Dwukierunkowość
- Pierwsze kroki z aplikacją Accessibility Scanner
- TalkBack
- Gesty TalkBack
- Dokumentacja dotycząca elementów rysowalnych
- Deskryptory treści
- Grupowanie treści
- Aktywne regiony
- Obiekty rysowalne NinePatch
- Narzędzie do rysowania obrazu 9-patch
- Chipsy
ChipGroup
- Ciemny motyw
- Motywy kolorystyczne
- Narzędzie do kolorów
- Animowanie grafiki rysowanej
Inne zasoby:
- Tworzenie aplikacji na Androida w języku Kotlin (kurs na Udacity)
- Kotlin Bootcamp for Programmers (kurs Udacity)
- Codelaby z kursu Kotlin Bootcamp for Programmers
W tej sekcji znajdziesz listę możliwych zadań domowych dla uczniów, którzy wykonują ten moduł w ramach kursu prowadzonego przez instruktora. Nauczyciel musi:
- W razie potrzeby przypisz pracę domową.
- Poinformuj uczniów, jak przesyłać projekty.
- Oceń zadania domowe.
Instruktorzy mogą korzystać z tych sugestii w dowolnym zakresie i mogą zadawać inne zadania domowe, które uznają za odpowiednie.
Jeśli wykonujesz ten kurs samodzielnie, możesz użyć tych zadań domowych, aby sprawdzić swoją wiedzę.
Pytanie 1
Które z tych elementów są obowiązkowe w przypadku obsługi języków zapisywanych od prawej do lewej?
▢ Zastąp Left
i Right
we właściwościach wartościami Start
i End
▢ Przełącz na język zapisywany od prawej do lewej
▢ Upewnij się, że wszystkie ikony używają android:autoMirrored="true"
.
▢ Podaj opisy treści
Pytanie 2
Które z tych narzędzi ułatwień dostępu jest wbudowane w większość urządzeń z Androidem?
▢ TalkBack
▢ Accessibility Scanner
▢ W Android Studio kliknij Refactor > Add RTL support where possible (Refaktoryzacja > Dodaj obsługę języków pisanych od prawej do lewej, jeśli to możliwe).
▢ Lint
Pytanie 3
Które z tych stwierdzeń dotyczących chipsów nie jest prawdziwe?
▢ Wyświetlasz komponenty w ramach ChipGroup
.
▢ Możesz podać listę stanów kolorów dla ChipGroup
.
▢ Elementy to drobne elementy reprezentujące atrybut, działanie lub tekst do wpisania.
▢ Jeśli aplikacja korzysta z elementów interfejsu, musisz zawsze włączyć DarkTheme
.
Pytanie 4
Który motyw zapewnia style dla trybu ciemnego i jasnego?
▢ DayNight
▢ DarkTheme
▢ DarkAndLightTheme
▢ Light
Pytanie 5
Czym jest region na żywo?
▢ Węzeł zawierający informacje ważne dla użytkownika
▢ Obszar ekranu, który zmienia kształt zgodnie z wytycznymi Material Design.
▢ Widok, który umożliwia przesyłanie strumieniowe wideo
▢ animowany obiekt rysowalny,