Style i motywy

Wypróbuj Compose
Jetpack Compose to zalecany zestaw narzędzi do tworzenia interfejsu na Androida. Dowiedz się, jak pracować z motywami w Compose.

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, które określają wygląd pojedynczego elementu View. Styl może określać atrybuty takie jak kolor i rozmiar czcionki, kolor tła i wiele innych.

Motyw to zbiór atrybutów, które są stosowane 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 każdy z obsługiwanych atrybutów motywu. Motywy mogą też stosować style do elementów, które nie są widokami, 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. Dwa 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 konkretnego typu widoku. Na przykład jeden styl może określać atrybuty przycisku. Każdy atrybut określony w stylu można ustawić w pliku układu. Wyodrębnienie wszystkich atrybutów do stylu ułatwia ich używanie i obsługę w wielu widżetach.

Motyw definiuje kolekcję nazwanych zasobów, do których mogą odwoływać się style, układy, widżety itp. Motywy przypisują zasobom Androida nazwy semantyczne, takie jak colorPrimary.

Style i motywy są zaprojektowane tak, aby ze sobą współgrały. Możesz na przykład mieć styl, który określa, że jedna część przycisku to colorPrimary, a inna to 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 motywy i style ze sobą współpracują, znajdziesz w poście na blogu Android styling: themes vs styles (Stylizacja Androida: motywy a style).

Tworzenie i stosowanie stylu

Aby utworzyć nowy styl, otwórz plik res/values/styles.xml projektu. Aby utworzyć styl:

  1. Dodaj element <style> z nazwą, która jednoznacznie identyfikuje styl.
  2. Dodaj element <item> dla każdego atrybutu stylu, który chcesz zdefiniować. Element name w każdym elemencie określa atrybut, którego używasz jako atrybutu XML w układzie. Wartość w elemencie <item> jest wartością tego atrybutu.

Załóżmy na przykład, że definiujesz taki 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 widok go akceptuje. Widok ignoruje wszystkie atrybuty, których nie akceptuje.

Zamiast jednak stosować styl do poszczególnych widoków, zwykle stosuje się style jako motyw dla całej aplikacji, aktywności lub kolekcji 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 zastąpić dziedziczone atrybuty stylu i dodać nowe.

Możesz na przykład odziedziczyć domyślny wygląd tekstu na platformie Androida i zmodyfikować go w ten sposób:

<style name="GreenText" parent="@android:style/TextAppearance">
    <item name="android:textColor">#00FF00</item>
</style>

Zawsze jednak dziedzicz podstawowe style aplikacji z Biblioteki pomocy Androida. Style w bibliotece pomocy zapewniają zgodność, optymalizując każdy styl pod kątem atrybutów interfejsu dostępnych w poszczególnych wersjach. Style biblioteki pomocy często mają nazwę podobną do stylu platformy, ale zawierają 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 kod 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 tych z platformy), rozszerzając nazwę stylu za pomocą notacji kropkowej, zamiast używać atrybutu parent. Oznacza to, że przed nazwą stylu należy dodać nazwę stylu, który chcesz odziedziczyć, oddzielając je kropką. Zwykle robi się to tylko podczas rozszerzania własnych stylów, a nie stylów z innych bibliotek. Na przykład ten styl dziedziczy wszystkie style z elementu GreenText z poprzedniego przykładu, a następnie zwiększa rozmiar tekstu:

<style name="GreenText.Large">
    <item name="android:textSize">22dp</item>
</style>

Możesz dziedziczyć style w ten sposób dowolną liczbę razy, dodając kolejne nazwy.

Aby dowiedzieć się, które atrybuty można zadeklarować za pomocą tagu <item>, zapoznaj się z tabelą „Atrybuty XML” w różnych dokumentacjach klas. Wszystkie widoki obsługują atrybuty XML z klasy bazowej View, a wiele widoków dodaje własne atrybuty specjalne. Na przykład atrybuty XML TextView obejmują atrybut android:inputType, który można zastosować do widoku tekstu otrzymującego dane wejściowe, takiego jak widżet EditText.

Stosowanie stylu jako motywu

Motyw możesz utworzyć w taki sam sposób jak style. Różnica polega na sposobie zastosowania: zamiast stosować styl z atrybutem style w widoku, stosujesz motyw z atrybutem android:theme w tagu <application> lub <activity> w pliku AndroidManifest.xml.

Oto przykład, jak zastosować ciemny motyw Material Design z Biblioteki pomocy Androida w 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 obsługiwane style zdefiniowane w danym motywie. Jeśli widok obsługuje tylko niektóre atrybuty zadeklarowane w stylu, stosuje tylko te atrybuty, a ignoruje te, których nie obsługuje.

Od Androida 5.0 (interfejs API na poziomie 21) i Biblioteki pomocy Androida w wersji 22.1 możesz też określić atrybut android:theme widoku w pliku układu. Spowoduje to zmianę motywu dla 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 taki jak Theme.AppCompat, który jest dostarczany przez Bibliotekę pomocy Androida. Zwykle jednak chcesz dostosować motyw do marki aplikacji. Najlepszym sposobem 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 automatycznie.

Wybierając sposób stylizowania aplikacji, pamiętaj o hierarchii stylów Androida. Ogólna zasada jest taka, aby w celu zachowania spójności jak najczęściej używać motywów i stylów. Jeśli określisz te same atrybuty w kilku miejscach, poniższa lista określa, które atrybuty zostaną ostatecznie zastosowane. Lista jest uporządkowana od najwyższego do najniższego priorytetu.

  1. stosowanie stylów na poziomie znaków lub akapitów za pomocą rozpiętości tekstu do klas pochodnych od TextView;
  2. stosowanie atrybutów automatycznie,
  3. Zastosowanie poszczególnych atrybutów bezpośrednio do widoku.
  4. Zastosowanie stylu do widoku.
  5. Styl domyślny.
  6. Zastosowanie motywu do kolekcji widoków, aktywności lub całej aplikacji.
  7. stosowanie określonego stylu widoku, np. ustawianie TextAppearance w TextView;

Rysunek 2. Stylizacja z span zastępuje stylizację z textAppearance.

TextAppearance

Jednym z ograniczeń stylów jest to, że do elementu View możesz zastosować tylko jeden styl. W elemencie TextView możesz jednak określić atrybut TextAppearance, który działa podobnie do stylu, jak w tym przykładzie:

<TextView
    ...
    android:textAppearance="@android:style/TextAppearance.Material.Headline"
    android:text="This text is styled via textAppearance!" />

TextAppearance pozwala zdefiniować styl tekstu, pozostawiając styl View 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 stylów, które oferuje TextView. Pełną listę atrybutów znajdziesz w TextAppearance.

Niektóre typowe atrybuty TextView, które nie są uwzględnione, to lineHeight[Multiplier|Extra], lines, breakStrategy i hyphenationFrequency. TextAppearance działa na poziomie znaków, a nie akapitów, 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, zgodnie z definicją w pliku styles.xml projektu. Ten styl AppTheme rozszerza motyw z biblioteki pomocniczej i zawiera zastąpienia atrybutów kolorów, które są używane przez kluczowe elementy interfejsu, takie jak pasek aplikacji i pływający przycisk polecenia (jeśli jest używany). 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 jest plik, który edytujesz, aby zmienić kolory. Zapoznaj się z Przeglądem kolorów w Material Design, aby poprawić wrażenia użytkowników dzięki dynamicznym kolorom i dodatkowym spersonalizowanym kolorom.

Gdy poznasz kolory, zaktualizuj wartości w pliku 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>

Następnie możesz zastąpić dowolne 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żyć w motywie, znajdziesz w tabeli atrybutów na stronie 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 dokumentacji klasy widoku. Na przykład wszystkie widoki obsługują atrybuty XML z podstawowej klasy View.

Większość atrybutów jest stosowana do określonych typów widoków, a niektóre do wszystkich widoków. Jednak niektóre atrybuty motywu wymienione na stronie R.styleable.Theme dotyczą okna aktywności, a nie 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 po rozpoczęciu aktywności. Więcej informacji znajdziesz w sekcji Rozpoczynanie aktywności za pomocą animacji.

Biblioteka pomocy Androida udostępnia też inne atrybuty, których możesz użyć do dostosowania motywu rozszerzonego z Theme.AppCompat, np. atrybut colorPrimary pokazany w poprzednim przykładzie. Najlepiej wyświetlać je w pliku attrs.xml biblioteki.

W bibliotece pomocy dostępne są też inne motywy, które możesz rozszerzyć zamiast tych pokazanych w poprzednim przykładzie. Dostępne motywy najlepiej sprawdzić w pliku themes.xml biblioteki.

Dodawanie stylów zależnych od wersji

Jeśli nowa wersja Androida dodaje atrybuty motywu, których chcesz użyć, możesz dodać je do motywu, zachowując zgodność ze starszymi wersjami. Wystarczy, że utworzysz 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

Style w pliku values/styles.xml są dostępne we wszystkich wersjach, więc motywy w pliku values-v21/styles.xml mogą je dziedziczyć. Oznacza to, że możesz uniknąć powielania stylów, zaczynając od motywu „podstawowego”, a następnie rozszerzając go w stylach specyficznych dla danej wersji.

Na przykład aby zadeklarować przejścia okien w Androidzie 5.0 (poziom interfejsu API 21) i nowszych wersjach, musisz użyć nowych atrybutów. 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 dla konkretnej wersji w pliku 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 dla każdej wersji systemu.

Więcej informacji o używaniu zasobów alternatywnych na różnych urządzeniach znajdziesz w artykule o udostępnianiu zasobów alternatywnych.

Dostosowywanie stylów widżetów

Każdy widżet w platformie i bibliotece pomocniczej ma styl domyślny. Jeśli na przykład stylizujesz aplikację za pomocą motywu z biblioteki pomocniczej, instancja Button jest stylizowana za pomocą stylu Widget.AppCompat.Button. Jeśli chcesz zastosować inny styl widżetu do przycisku, możesz to zrobić za pomocą atrybutu style w pliku układu. Na przykład poniższy 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 go zadeklarować w pliku 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 rozszerzasz inne style, a następnie stosować niestandardowy 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