Dobrze zaprojektowany widok niestandardowy nie różni się niczym od innych dobrze zaprojektowanych zajęć. Obejmuje on określony zestaw funkcji za pomocą prostego interfejsu, wydajnie wykorzystuje procesor i pamięć itd. Dobrze zaprojektowana klasa musi spełniać te wymagania:
- Zgodność ze standardami Androida.
- Podaj niestandardowe atrybuty, które można stylizować z układami XML na Androidzie.
- Wysyłaj zdarzenia ułatwień dostępu.
- być zgodna z wieloma platformami Androida,
Platforma Android udostępnia zestaw klas podstawowych i tagów XML, które ułatwiają tworzenie widoku danych spełniającego wszystkie te wymagania. Z tej lekcji dowiesz się, jak za pomocą platformy Androida utworzyć główną funkcję klasy widoku danych.
Więcej informacji znajdziesz w sekcji Komponenty widoku niestandardowego.
Podklasyfikuj widok
Wszystkie klasy widoku danych zdefiniowane w platformie Androida rozszerzają zakres View
. Widok niestandardowy możesz też rozszerzyć bezpośrednio o View
. Możesz też zaoszczędzić czas, rozszerzając jedną z istniejących podklas widoku, np. Button
.
Aby umożliwić Android Studio interakcję z widokiem danych, musisz udostępnić przynajmniej konstruktor, którego parametry to obiekty Context
i AttributeSet
.
Ten konstruktor umożliwia edytorowi układu tworzenie i edytowanie instancji widoku.
Kotlin
class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)
Java
class PieChart extends View { public PieChart(Context context, AttributeSet attrs) { super(context, attrs); } }
Zdefiniuj atrybuty niestandardowe
Aby dodać wbudowanego View
do interfejsu, określ go w elemencie XML i określ jego wygląd i działanie za pomocą atrybutów elementu. Widoki niestandardowe i stylizacje można
dodawać za pomocą XML. Aby włączyć to zachowanie w widoku niestandardowym:
- Zdefiniuj atrybuty niestandardowe dla widoku w elemencie zasobu
<declare-styleable>
. - Określ wartości atrybutów w układzie XML.
- Pobieranie wartości atrybutów w czasie działania.
- Zastosuj pobrane wartości atrybutów do widoku.
W tej sekcji omówiono sposób definiowania atrybutów niestandardowych i określania ich wartości. W następnej sekcji omawiamy pobieranie i stosowanie wartości w czasie działania.
Aby zdefiniować atrybuty niestandardowe, dodaj do projektu zasoby (<declare-styleable>
). Zazwyczaj umieszcza się te zasoby w pliku res/values/attrs.xml
. Oto przykład pliku attrs.xml
:
<resources> <declare-styleable name="PieChart"> <attr name="showText" format="boolean" /> <attr name="labelPosition" format="enum"> <enum name="left" value="0"/> <enum name="right" value="1"/> </attr> </declare-styleable> </resources>
Ten kod deklaruje 2 atrybuty niestandardowe (showText
i labelPosition
), które należą do encji PieChart
, którą można stylizować. Nazwa elementu z możliwością stylizacji jest zgodnie z konwencją taka sama jak nazwa klasy definiującej widok niestandardowy. Chociaż nie jest to konieczne, wielu popularnych edytorów kodu korzysta z tej konwencji nazewnictwa, aby zapewnić uzupełnianie instrukcji.
Po zdefiniowaniu atrybutów niestandardowych możesz ich używać w plikach XML układu, tak jak w atrybutach wbudowanych. Jedyną różnicą jest to, że atrybuty niestandardowe należą do innej przestrzeni nazw. Zamiast należeć do przestrzeni nazw http://schemas.android.com/apk/res/android
, należą one do http://schemas.android.com/apk/res/[your package name]
. Atrybutów zdefiniowanych dla atrybutu PieChart
można użyć np. w ten sposób:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto"> <com.example.customviews.charting.PieChart custom:showText="true" custom:labelPosition="left" /> </LinearLayout>
Aby uniknąć powtarzania identyfikatora URI długiej przestrzeni nazw, w przykładzie użyto dyrektywy xmlns
. Ta dyrektywa przypisuje alias custom
do przestrzeni nazw http://schemas.android.com/apk/res/com.example.customviews
.
Możesz wybrać dowolny alias dla swojej przestrzeni nazw.
Zwróć uwagę na nazwę tagu XML, który dodaje do układu widok niestandardowy. Jest to pełna i jednoznaczna nazwa klasy widoku niestandardowego. Jeśli klasa widoku danych jest klasą wewnętrzną, możesz ją dodatkowo zakwalifikować na podstawie nazwy klasy zewnętrznej widoku.
Na przykład klasa PieChart
ma klasę wewnętrzną o nazwie PieView
. Aby użyć atrybutów niestandardowych z tej klasy, użyj tagu com.example.customviews.charting.PieChart$PieView
.
Zastosuj atrybuty niestandardowe
Gdy widok jest tworzony na podstawie układu XML, wszystkie atrybuty w tagu XML są odczytywane z pakietu zasobów i przekazywane do konstruktora widoku jako element AttributeSet
.
Możesz odczytywać wartości bezpośrednio z AttributeSet
, ale ma to kilka wad:
- Odwołania do zasobów w wartościach atrybutów nie są rozpoznawane.
- Style nie są stosowane.
Zamiast tego przekaż AttributeSet
do obtainStyledAttributes()
.
Ta metoda zwraca tablicę wartości TypedArray
, do których zastosowano już odniesienie i styl.
Kompilator zasobów Androida wykonuje wiele zadań, aby ułatwić Ci wywoływanie funkcji obtainStyledAttributes()
. Dla każdego zasobu <declare-styleable>
w katalogu res/
wygenerowany R.java
definiuje zarówno tablicę identyfikatorów atrybutów, jak i zbiór stałych, które definiują indeks każdego atrybutu w tablicy. Do odczytu atrybutów z: TypedArray
możesz używać wstępnie zdefiniowanych stałych. Klasa PieChart
odczytuje swoje atrybuty w ten sposób:
Kotlin
init { context.theme.obtainStyledAttributes( attrs, R.styleable.PieChart, 0, 0).apply { try { mShowText = getBoolean(R.styleable.PieChart_showText, false) textPos = getInteger(R.styleable.PieChart_labelPosition, 0) } finally { recycle() } } }
Java
public PieChart(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.PieChart, 0, 0); try { mShowText = a.getBoolean(R.styleable.PieChart_showText, false); textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0); } finally { a.recycle(); } }
Pamiętaj, że obiekty TypedArray
są zasobami współdzielonymi i po użyciu należy je odświeżyć.
Dodaj usługi i zdarzenia
Atrybuty to skuteczny sposób kontrolowania zachowania i wyglądu widoków, ale można je odczytać tylko po zainicjowaniu widoku. Aby zapewnić dynamiczne zachowanie, udostępnij parę metody pobierania i ustawiającego właściwości dla każdego atrybutu niestandardowego. Ten fragment kodu pokazuje, jak PieChart
ujawnia właściwość o nazwie showText
:
Kotlin
fun isShowText(): Boolean { return mShowText } fun setShowText(showText: Boolean) { mShowText = showText invalidate() requestLayout() }
Java
public boolean isShowText() { return mShowText; } public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout(); }
Zwróć uwagę, że setShowText
wywołuje metody invalidate()
i requestLayout()
. Te wywołania mają kluczowe znaczenie dla niezawodności widoku. Musisz unieważnić widok po każdej zmianie jego właściwości, która może zmienić jego wygląd, aby system wiedział, że trzeba go przerysować. Nowy układ musisz też zgłosić, jeśli właściwość zmieni się w sposób, który może mieć wpływ na rozmiar lub kształt widoku. Zapominanie tych wywołań metody może spowodować, że błędy będą trudne do znalezienia.
Widoki niestandardowe muszą też obsługiwać detektory zdarzeń, aby przekazywać ważne zdarzenia. Na przykład PieChart
udostępnia zdarzenie niestandardowe o nazwie OnCurrentItemChanged
, aby powiadamiać odbiorniki o tym, że użytkownik obrócił wykres kołowy, aby zaznaczyć nowy wycinek kołowy.
Łatwo zapomnieć o wyświetleniu właściwości i zdarzeń, zwłaszcza jeśli jesteś jedynym użytkownikiem tego widoku niestandardowego. Poświęcenie czasu na dokładne zdefiniowanie interfejsu widoku pozwala obniżyć koszty jego konserwacji w przyszłości. Pamiętaj, by zawsze ujawniać wszystkie właściwości, które wpływają na widoczny wygląd lub działanie widoku niestandardowego.
Projektowanie z myślą o dostępności
Widok niestandardowy musi obsługiwać szeroki zakres użytkowników. Dotyczy to także użytkowników z niepełnosprawnościami, które uniemożliwiają wyświetlanie i używanie ekranu dotykowego. Aby zapewnić pomoc użytkownikom z niepełnosprawnościami, wykonaj te czynności:
- Oznacz pola do wprowadzania danych za pomocą atrybutu
android:contentDescription
. - Wysyłaj zdarzenia ułatwień dostępu, wywołując w razie potrzeby
sendAccessibilityEvent()
. - Korzystaj z innych kontrolerów, takich jak pad kierunkowy lub kulka.
Więcej informacji o tworzeniu widoków ułatwień dostępu znajdziesz w artykule o ułatwianiu ułatwień dostępu w aplikacjach.