Style i motywy na Androidzie pozwalają oddzielić szczegóły projektu aplikacji od struktury i zachowania interfejsu, podobnie jak arkusze stylów w projektowaniu stron internetowych.
Styl to zbiór atrybutów określających wygląd pojedynczego elementu View. Styl może określać atrybuty takie jak kolor czcionki, rozmiar czcionki, kolor tła i wiele innych.
Motyw to zbiór atrybutów, który jest stosowany do całej aplikacji, aktywności lub hierarchii widoków, a nie tylko do pojedynczego widoku. Gdy zastosujesz motyw, każdy widok w aplikacji lub aktywności zastosuje wszystkie obsługiwane atrybuty motywu. Motywy mogą też stosować style do elementów innych niż widoki, takich jak pasek stanu i tło okna.
Style i motywy są deklarowane w
pliku zasobów stylu w
res/values/, zwykle o nazwie styles.xml.
Rysunek 1. 2 motywy zastosowane do tej samej aktywności:
Theme.AppCompat (po lewej) i Theme.AppCompat.Light (po prawej).
Motywy a style
Motywy i style mają wiele podobieństw, ale są używane do różnych celów. Motywy i style mają tę samą podstawową strukturę – parę klucz-wartość, która mapuje atrybuty na zasoby.
Styl określa atrybuty dla określonego typu widoku. Na przykład jeden styl może określać atrybuty przycisku. Każdy atrybut określony w stylu jest atrybutem, który można ustawić w pliku układu. Wyodrębnienie wszystkich atrybutów do stylu ułatwia ich używanie i utrzymywanie w wielu widżetach.
Motyw definiuje zbiór nazwanych zasobów, do których można się odwoływać w stylach, układach, widżetach itp. Motywy przypisują nazwy semantyczne, takie jak colorPrimary, do zasobów Androida.
Style i motywy mają ze sobą współpracować. Możesz na przykład mieć styl, który określa, że jedna część przycisku ma kolor colorPrimary, a druga – colorSecondary. Rzeczywiste definicje tych kolorów są podane w motywie. Gdy urządzenie przejdzie w tryb nocny, aplikacja może przełączyć się z motywu „jasnego” na „ciemny”, zmieniając wartości wszystkich tych nazw zasobów. Nie musisz zmieniać stylów, ponieważ używają one nazw semantycznych, a nie konkretnych definicji kolorów.
Więcej informacji o tym, jak działają motywy i style, znajdziesz w poście na blogu Android styling: themes vs styles.
Tworzenie i stosowanie stylu
Aby utworzyć nowy styl, otwórz plik res/values/styles.xml w projekcie. Aby utworzyć każdy styl, wykonaj te czynności:
- Dodaj element
<style>z nazwą, która jednoznacznie identyfikuje styl. - Dodaj element
<item>dla każdego atrybutu stylu, który chcesz zdefiniować. Wartośćnamew każdym elemencie określa atrybut, którego w przeciwnym razie używasz jako atrybutu XML w układzie. Wartość w elemencie<item>jest wartością tego atrybutu.
Załóżmy na przykład, że definiujesz ten styl:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style> </resources>
Styl możesz zastosować do widoku w ten sposób:
<TextView style="@style/GreenText" ... />
Każdy atrybut określony w stylu jest stosowany do tego widoku, jeśli go akceptuje. Widok ignoruje wszystkie atrybuty, których nie akceptuje.
Zamiast stosować styl do poszczególnych widoków, zwykle stosujesz style jako motyw do całej aplikacji, aktywności lub zbioru widoków, jak opisano w innej sekcji tego przewodnika.
Rozszerzanie i dostosowywanie stylu
Podczas tworzenia własnych stylów zawsze rozszerzaj istniejący styl z platformy lub biblioteki pomocy, aby zachować zgodność ze stylami interfejsu platformy. Aby rozszerzyć styl, określ styl, który chcesz rozszerzyć, za pomocą atrybutu parent. Możesz wtedy zastąpić odziedziczone atrybuty stylu i dodać nowe.
Możesz na przykład odziedziczyć domyślny wygląd tekstu na platformie Android i zmodyfikować go w ten sposób:
<style name="GreenText" parent="@android:style/TextAppearance"> <item name="android:textColor">#00FF00</item> </style>
Style podstawowe aplikacji zawsze dziedzicz z biblioteki pomocy Androida. Style w bibliotece pomocy zapewniają zgodność, optymalizując każdy styl pod kątem atrybutów interfejsu dostępnych w każdej wersji. Style biblioteki pomocy często mają nazwę podobną do stylu z platformy, ale z dopiskiem AppCompat.
Aby odziedziczyć style z biblioteki lub własnego projektu, zadeklaruj nazwę stylu nadrzędnego bez części @android:style/ pokazanej w poprzednim przykładzie. Na przykład ten przykład dziedziczy style wyglądu tekstu z biblioteki pomocy:
<style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style>
Możesz też dziedziczyć style – z wyjątkiem stylów z platformy – rozszerzając nazwę stylu za pomocą notacji z kropką, zamiast używać atrybutu parent. Oznacza to, że nazwę stylu należy poprzedzić nazwą stylu, który chcesz odziedziczyć, oddzieloną kropką. Zwykle robisz to tylko wtedy, gdy rozszerzasz własne style, a nie style z innych bibliotek. Na przykład ten styl dziedziczy wszystkie style z elementu GreenText w poprzednim przykładzie, a następnie zwiększa rozmiar tekstu:
<style name="GreenText.Large"> <item name="android:textSize">22dp</item> </style>
Możesz kontynuować dziedziczenie stylów w ten sposób, dodając kolejne nazwy.
Aby dowiedzieć się, które atrybuty możesz zadeklarować za pomocą tagu <item>, zapoznaj się z tabelą „Atrybuty XML
” w różnych odniesieniach do klas. Wszystkie widoki obsługują
atrybuty XML z podstawowej
View klasy, a wiele widoków dodaje własne atrybuty specjalne. Na przykład atrybuty XML
TextViewobejmują atrybut
android:inputType
, który możesz zastosować do widoku tekstowego, który przyjmuje dane wejściowe, np. widżet
EditText.
Stosowanie stylu jako motywu
Motyw możesz utworzyć w taki sam sposób jak style. Różnica polega na sposobie jego stosowania:
zamiast stosować styl za pomocą atrybutu style w widoku, stosujesz motyw za pomocą
atrybutu android:theme w tagu <application> lub
<activity> w pliku AndroidManifest.xml.
Oto jak zastosować motyw „ciemny” Material Design z biblioteki pomocy Androida do całej aplikacji:
<manifest ... > <application android:theme="@style/Theme.AppCompat" ... > </application> </manifest>
A oto jak zastosować motyw „jasny” tylko do jednej aktywności:
<manifest ... > <application ... > <activity android:theme="@style/Theme.AppCompat.Light" ... > </activity> </application> </manifest>
Każdy widok w aplikacji lub aktywności stosuje style, które obsługuje, zdefiniowane w danym motywie. Jeśli widok obsługuje tylko niektóre atrybuty zadeklarowane w stylu, stosuje tylko te atrybuty i ignoruje te, których nie obsługuje.
Od Androida 5.0 (poziom 21 interfejsu API) i biblioteki pomocy Androida w wersji 22.1 możesz też określić atrybut android:theme w widoku w pliku układu. Modyfikuje to motyw tego widoku i wszystkich widoków podrzędnych, co jest przydatne do zmiany palet kolorów motywu w określonej części interfejsu.
Poprzednie przykłady pokazują, jak zastosować motyw, np. Theme.AppCompat, który jest dostarczany przez bibliotekę pomocy Androida. Zwykle jednak chcesz dostosować motyw do marki aplikacji. Najlepszym sposobem na to jest rozszerzenie tych stylów z biblioteki pomocy i zastąpienie niektórych atrybutów, jak opisano w następnej sekcji.
Hierarchia stylów
Android udostępnia różne sposoby ustawiania atrybutów w aplikacji na Androida. Możesz na przykład ustawić atrybuty bezpośrednio w układzie, zastosować styl do widoku, zastosować motyw do układu, a nawet ustawić atrybuty programowo.
Podczas wybierania sposobu stylizowania aplikacji pamiętaj o hierarchii stylów Androida. Aby zachować spójność, używaj motywów i stylów jak najczęściej. Jeśli określisz te same atrybuty w kilku miejscach, ostatecznie zostaną zastosowane atrybuty z tej listy. Lista jest uporządkowana od najwyższego do najniższego priorytetu.
- Stosowanie stylów na poziomie znaku lub akapitu za pomocą zakresów tekstu w klasach pochodnych
TextView. - Stosowanie atrybutów programowo.
- Stosowanie poszczególnych atrybutów bezpośrednio do widoku.
- Stosowanie stylu do widoku.
- Styl domyślny.
- Stosowanie motywu do zbioru widoków, aktywności lub całej aplikacji.
- Stosowanie określonych stylów specyficznych dla widoku, np. ustawianie a
TextAppearancewTextView.
Rysunek 2. Styl z elementu span zastępuje styl z elementu textAppearance.
TextAppearance
Jednym z ograniczeń stylów jest to, że do elementu View można zastosować tylko 1 styl. W elemencie TextView możesz jednak określić atrybut TextAppearance, który działa podobnie jak styl, jak pokazano w tym przykładzie:
<TextView ... android:textAppearance="@android:style/TextAppearance.Material.Headline" android:text="This text is styled via textAppearance!" />
TextAppearance umożliwia zdefiniowanie stylów specyficznych dla tekstu, pozostawiając styl elementu View dostępny do innych zastosowań. Pamiętaj jednak, że jeśli zdefiniujesz jakiekolwiek atrybuty tekstu bezpośrednio w elemencie View lub w stylu, te wartości zastąpią wartości TextAppearance.
TextAppearance obsługuje podzbiór atrybutów stylu, które oferuje TextView. Pełną listę atrybutów znajdziesz w sekcji TextAppearance.
Niektóre typowe TextView atrybuty, które nie są uwzględnione, to
lineHeight[Multiplier|Extra],
lines,
breakStrategy i
hyphenationFrequency.
TextAppearance działa na poziomie znaku, a nie akapitu, więc
atrybuty, które wpływają na cały układ, nie są obsługiwane.
Dostosowywanie motywu domyślnego
Gdy tworzysz projekt w Android Studio, domyślnie stosuje on do aplikacji motyw Material Design zdefiniowany w pliku styles.xml projektu. Ten AppTheme styl rozszerza motyw z Biblioteki pomocy i zawiera zastąpienia atrybutów kolorów używanych przez kluczowe elementy interfejsu, takie jak pasek aplikacji i pływający przycisk polecenia (FAB), jeśli są używane. Możesz więc szybko dostosować kolorystykę aplikacji, aktualizując podane kolory.
Na przykład plik styles.xml wygląda podobnie do tego:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
Wartości stylu są w rzeczywistości odwołaniami do innych
zasobów kolorów zdefiniowanych w
pliku res/values/colors.xml projektu. To właśnie ten plik edytujesz, aby zmienić kolory.
Aby poprawić wrażenia użytkownika dzięki dynamicznym kolorom i dodatkowym spersonalizowanym kolorom, zapoznaj się z
omówieniem kolorów Material Design.
Gdy znasz już kolory, zaktualizuj wartości w res/values/colors.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Color for the app bar and other primary UI elements. --> <color name="colorPrimary">#3F51B5</color> <!-- A darker variant of the primary color, used for the status bar (on Android 5.0+) and contextual app bars. --> <color name="colorPrimaryDark">#303F9F</color> <!-- a secondary color for controls like checkboxes and text fields. --> <color name="colorAccent">#FF4081</color> </resources>
Możesz wtedy zastąpić inne style. Możesz na przykład zmienić kolor tła aktywności w ten sposób:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <item name="android:windowBackground">@color/activityBackground</item> </style>
Listę atrybutów, których możesz używać w motywie, znajdziesz w tabeli atrybutów w R.styleable.Theme. Podczas dodawania stylów do widoków w układzie możesz też znaleźć atrybuty, przeglądając tabelę „Atrybuty XML” w odniesieniach do klas widoków. Na przykład wszystkie widoki obsługują
atrybuty XML z podstawowej View
klasy.
Większość atrybutów jest stosowana do określonych typów widoków, a niektóre do wszystkich widoków. Niektóre atrybuty motywu wymienione w R.styleable.Theme są jednak stosowane do okna aktywności, a nie do widoków w układzie. Na przykład windowBackground zmienia tło okna, a windowEnterTransition definiuje animację przejścia, która ma być używana podczas uruchamiania aktywności. Więcej informacji znajdziesz w artykule Uruchamianie aktywności za pomocą animacji.
Biblioteka pomocy Androida udostępnia też inne atrybuty, których możesz używać do dostosowywania motywu rozszerzonego z Theme.AppCompat, np. atrybut colorPrimary pokazany w poprzednim przykładzie. Najlepiej je wyświetlić w pliku
biblioteki attrs.xml.
W bibliotece pomocy dostępne są też inne motywy, które możesz rozszerzyć zamiast tych pokazanych w poprzednim przykładzie. Najlepszym miejscem, aby zobaczyć dostępne motywy, jest
plik
biblioteki themes.xml.
Dodawanie stylów specyficznych dla wersji
Jeśli nowa wersja Androida dodaje atrybuty motywu, których chcesz używać, możesz dodać je do motywu, zachowując zgodność ze starszymi wersjami. Wystarczy, że zapiszesz kolejny plik styles.xml w katalogu values, który zawiera kwalifikator wersji zasobu:
res/values/styles.xml # themes for all versions res/values-v21/styles.xml # themes for API level 21+ only
Ponieważ style w pliku values/styles.xml są dostępne we wszystkich wersjach, motywy w values-v21/styles.xml mogą je dziedziczyć. Oznacza to, że możesz uniknąć duplikowania stylów, zaczynając od motywu „podstawowego”, a następnie rozszerzając go w stylach specyficznych dla wersji.
Aby na przykład zadeklarować przejścia okien w Androidzie 5.0 (poziom 21 interfejsu API) i nowszych wersjach, musisz użyć nowych atrybutów. Twój motyw podstawowy w res/values/styles.xml może wyglądać tak:
<resources> <!-- Base set of styles that apply to all versions. --> <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/primaryColor</item> <item name="colorPrimaryDark">@color/primaryTextColor</item> <item name="colorAccent">@color/secondaryColor</item> </style> <!-- Declare the theme name that's actually applied in the manifest file. --> <style name="AppTheme" parent="BaseAppTheme" /> </resources>
Następnie dodaj style specyficzne dla wersji w res/values-v21/styles.xml w ten sposób:
<resources> <!-- extend the base theme to add styles available only with API level 21+ --> <style name="AppTheme" parent="BaseAppTheme"> <item name="android:windowActivityTransitions">true</item> <item name="android:windowEnterTransition">@android:transition/slide_right</item> <item name="android:windowExitTransition">@android:transition/slide_left</item> </style> </resources>
Teraz możesz zastosować AppTheme w pliku manifestu, a system wybierze style dostępne w każdej wersji systemu.
Więcej informacji o używaniu alternatywnych zasobów na różnych urządzeniach znajdziesz w artykule Udostępnianie alternatywnych zasobów.
Dostosowywanie stylów widżetów
Każdy widżet w platformie i bibliotece pomocy ma styl domyślny. Jeśli na przykład stylizujesz aplikację za pomocą motywu z biblioteki pomocy, instancja
Button jest stylizowana za pomocą stylu
Widget.AppCompat.Button. Jeśli chcesz zastosować do przycisku inny styl widżetu, możesz to zrobić za pomocą atrybutu style w pliku układu. Na przykład ten kod stosuje styl przycisku bez obramowania z biblioteki:
<Button style="@style/Widget.AppCompat.Button.Borderless" ... />
Jeśli chcesz zastosować ten styl do wszystkich przycisków, możesz zadeklarować go w buttonStyle motywu w ten sposób:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item> ... </style>
Możesz też rozszerzać style widżetów, tak jak każdy inny styl, a następnie stosować własny styl widżetu w układzie lub motywie.
Dodatkowe materiały
Więcej informacji o motywach i stylach znajdziesz w tych materiałach:
Posty na blogu
- Android styling: themes vs styles
- Android styling: common theme attributes
- Android styling: prefer theme attributes