Style i motywy

Wypróbuj tworzenie wiadomości
Jetpack Compose to zalecany zestaw narzędzi interfejsu na Androida. Dowiedz się, jak pracować z motywami w sekcji Redagowanie.

Style i motywy w Androidzie umożliwiają oddzielenie szczegółów projektu aplikacji od struktury i zachowania interfejsu użytkownika, podobnie jak w przypadku arkuszy stylów w projektowaniu stron internetowych.

Style to zbiór atrybutów określający wygląd pojedynczego elementu View. Styl może określać atrybuty, takie jak kolor czcionki, rozmiar czcionki, kolor tła itp.

Motyw to zbiór atrybutów stosowanych do całej aplikacji, aktywności lub hierarchii widoku, a nie tylko do pojedynczego widoku. Gdy zastosujesz motyw, w każdym widoku w aplikacji lub działaniu będą stosowane wszystkie obsługiwane atrybuty motywu. Motywy mogą też stosować style do elementów, które nie są widoczne, takich jak pasek stanu i tło okna.

Style i motywy są deklarowane w pliku zasobów stylu w res/values/, który zwykle nosi nazwę 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.

Atrybut style określa atrybuty dla danego typu widoku. Jeden styl może np. określać atrybuty przycisku. Każdy atrybut określony w stylu jest atrybutem, który możesz ustawić w pliku układu. Wyodrębnienie wszystkich atrybutów do stylu ułatwia ich używanie i przechowywanie w wielu widżetach.

Motyw definiuje kolekcję nazwanych zasobów, do których można odwoływać się w stylach, układach, widżetach itp. Motywy przypisują zasobom Androida nazwy semantyczne, takie jak colorPrimary.

Style i motywy powinny współdziałać ze sobą. Możesz na przykład użyć stylu, w którym jedna część przycisku ma kolor colorPrimary, a druga – colorSecondary. Rzeczywiste definicje tych kolorów są podane w motywie. Gdy urządzenie przełączy się w tryb nocny, aplikacja może zmienić motyw z „jasnego” na „ciemny”, zmieniając wartości wszystkich nazw zasobów. Nie musisz zmieniać stylów, ponieważ używają one nazw semantycznych, a nie konkretnych definicji kolorów.

Więcej informacji o współdziałaniu motywów i stylów znajdziesz w poście na blogu Styl Androida: motywy a style.

Tworzenie i stosowanie stylu

Aby utworzyć nowy styl, otwórz plik res/values/styles.xml projektu. W przypadku każdego stylu, który chcesz utworzyć, wykonaj te czynności:

  1. Dodaj element <style> o unikalnej nazwie identyfikującej styl.
  2. Dodaj element <item> dla każdego atrybutu stylu, który chcesz zdefiniować. Atrybut name w każdym elemencie określa atrybut, którego używasz w innym przypadku jako atrybut XML w swoim układzie. Wartość w elemencie <item> to wartość tego atrybutu.

Załóżmy na przykład, że zdefiniujesz następujący styl:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="GreenText" parent="TextAppearance.AppCompat">
        <item name="android:textColor">#00FF00</item>
    </style>
</resources>

Aby zastosować styl w widoku, wykonaj te czynności:

<TextView
    style="@style/GreenText"
    ... />

Każdy atrybut określony w stylu jest stosowany w widoku, jeśli widok go akceptuje. Widok ignoruje atrybuty, których nie akceptuje.

Zamiast jednak stosować styl do poszczególnych widoków, zwykle używasz styl jako motywu 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 ramy 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ć dziedziczone atrybuty stylu i dodać nowe.

Możesz na przykład odziedziczyć domyślny wygląd tekstu platformy Androida i zmodyfikować go w następujący sposób:

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

Jednak zawsze dziedzicz podstawowe style aplikacji z Android Support Library. Style w Bibliotece pomocy zapewniają zgodność dzięki optymalizacji poszczególnych stylów pod kątem atrybutów interfejsu użytkownika dostępnych w poszczególnych wersjach. Style biblioteki obsługi często mają nazwę podobną do stylu z platformy, ale z dodatkiem AppCompat.

Aby dziedziczyć style z biblioteki lub własnego projektu, określ nazwę stylu nadrzędnego bez części @android:style/ pokazanej w poprzednim przykładzie. Na przykład w tym przykładzie styl wyglądu tekstu jest dziedziczony z biblioteki Support Library:

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

Możesz też dziedziczyć style – z wyjątkiem tych z platformy – przez rozszerzenie nazwy stylu za pomocą notacji kropkowej, zamiast używania atrybutu parent. Oznacza to, że przed nazwą stylu należy umieścić nazwę stylu, który ma być dziedziczony, rozdzieloną kropką. Zazwyczaj 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 dziedziczyć style w taki sposób dowolną liczbę razy, dodając kolejne nazwy.

Informacje o tym, które atrybuty można zadeklarować za pomocą tagu <item>, znajdziesz w tabeli „Atrybuty XML” w różnych odwołaniach do klas. Wszystkie widoki obsługują atrybuty XML z podstawowej klasy View, a wiele widoków dodaje własne atrybuty specjalne. Na przykład atrybuty XML TextView zawierają atrybut android:inputType, który można zastosować do widoku tekstowego otrzymującego dane wejściowe, takiego jak widżet EditText.

Stosowanie stylu jako motywu

Motyw możesz utworzyć w taki sam sposób, w jaki tworzysz style. Różnica polega na sposobie zastosowania: zamiast stosowania stylu za pomocą atrybutu style w widoku, możesz zastosować motyw za pomocą atrybutu android:theme w tagu <application> lub <activity> w pliku AndroidManifest.xml.

Oto przykład zastosowania ciemnego motywu Material Design z Android Support Library do całej aplikacji:

<manifest ... >
    <application android:theme="@style/Theme.AppCompat" ... >
    </application>
</manifest>

A tak możesz zastosować motyw „light” 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, z tych zdefiniowanych w danym temacie. Jeśli widok obsługuje tylko niektóre atrybuty zadeklarowane w stylu, stosuje tylko te atrybuty i ignoruje te, których nie obsługuje.

Począwszy od Androida w wersji 5.0 (poziom interfejsu API 21) i Biblioteki pomocy Androida w wersji 22.1 możesz też określić atrybut android:theme w widoku w pliku układu. Spowoduje to zmodyfikowanie motywu w tym widoku i wszystkich widokach podrzędnych, co jest przydatne do zmiany palety kolorów motywu w konkretnej części interfejsu.

Poprzednie przykłady pokazują, jak zastosować motyw, taki jak Theme.AppCompat, który jest dostarczany przez bibliotekę wsparcia Androida. Zazwyczaj jednak warto 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ępującej sekcji.

Hierarchia stylów

Android oferuje wiele sposobów ustawiania atrybutów w aplikacji na to urządzenie. 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.

Wybierając styl aplikacji, weź pod uwagę hierarchię stylów Androida. Aby zachować spójność, staraj się używać motywów i stylów. Jeśli podasz te same atrybuty w kilku miejscach, o tym, które z nich zostaną ostatecznie zastosowane, decyduje poniższa lista. Lista jest posortowana od najwyższego do najniższego priorytetu.

  1. Stosowanie stylizacji na poziomie znaku lub akapitu za pomocą zakresów tekstu do klas pochodnych TextView.
  2. stosowanie atrybutów programowo;
  3. bezpośrednie stosowanie poszczególnych atrybutów do widoku;
  4. Stosowanie stylu do widoku
  5. Styl domyślny.
  6. Zastosuj motyw do zbioru widoków, aktywności lub całej aplikacji.
  7. Zastosowanie określonego stylu zależnego od widoku danych, np. ustawienia TextAppearance w elemencie TextView.

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

Wygląd tekstu

Jednym z ograniczeń stylów jest to, że do View można zastosować tylko jeden styl. W TextView możesz jednak także określić atrybut TextAppearance, który działa podobnie do stylu, 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 definiowanie stylów tekstowych, pozostawiając styl View do innych zastosowań. Pamiętaj jednak, że jeśli zdefiniujesz atrybuty tekstowe bezpośrednio w elementach View lub w stylu, zastąpią one wartości TextAppearance.

TextAppearance obsługuje podzbiór atrybutów stylu oferowanych przez TextView. Pełną listę atrybutów znajdziesz na stronie TextAppearance.

Niektóre typowe atrybuty TextView, które nie są uwzględniane, to: lineHeight[Multiplier|Extra], lines, breakStrategy i hyphenationFrequency. TextAppearance działa na poziomie znaków, a nie akapitu, dlatego atrybuty, które mają wpływ na cały układ, nie są obsługiwane.

Dostosowywanie motywu domyślnego

Gdy tworzysz projekt w Android Studio, domyślnie stosuje on motyw Material Design w aplikacji zgodnie z definicją w pliku styles.xml projektu. Ten styl AppTheme rozszerza motyw z biblioteki pomocy i zawiera zastąpienia atrybutów kolorów używanych przez kluczowe elementy interfejsu, takie jak pasek aplikacjipływający przycisk działania (jeśli jest używany). Dzięki temu możesz szybko dostosować kolorystykę aplikacji, zmieniając dostępne kolory.

Na przykład Twój 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 to w istocie odwołania do innych zasobów kolorów zdefiniowanych w pliku res/values/colors.xml projektu. To plik, który edytujesz, aby zmienić kolory. Zapoznaj się z przeglądem kolorów Material Design, aby zwiększyć wygodę użytkowników dzięki dynamicznym kolorom i dodatkowym kolorom niestandardowym.

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>

Możesz wtedy 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żywać w motywie, znajdziesz w tabeli atrybutów na stronie R.styleable.Theme. Przy dodawaniu stylów do widoków w układzie atrybuty można też znaleźć w tabeli „Atrybuty XML” w odwołaniach do klas widoku. Na przykład wszystkie widoki obsługują atrybuty XML z podstawowej klasy View.

Większość atrybutów jest stosowana w przypadku określonych typów widoków, a niektóre są stosowane do wszystkich widoków. Jednak niektóre atrybuty motywu wymienione na stronie R.styleable.Theme mają zastosowanie do 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 będzie wyświetlana po rozpoczęciu aktywności. Więcej informacji znajdziesz w artykule Rozpoczynanie aktywności za pomocą animacji.

Biblioteka pomocy Androida udostępnia też inne atrybuty, których możesz użyć do dostosowywania motywu rozszerzonego z poziomu Theme.AppCompat, np. atrybutu colorPrimary pokazanego w poprzednim przykładzie. Najlepiej oglądać je w pliku attrs.xml biblioteki.

W Bibliotece pomocy są też dostępne inne motywy, które warto rozszerzyć zamiast tych przedstawionych w poprzednim przykładzie. Najlepszym miejscem, w którym można zobaczyć dostępne tematy, jest plik themes.xmlbiblioteki.

Dodawanie stylów dla poszczególnych wersji

Jeśli w nowej wersji Androida pojawią się atrybuty motywu, których chcesz użyć, możesz dodać je do motywu, zachowując jego zgodność ze starszymi wersjami. Wystarczy, że utworzysz kolejny plik styles.xml i zapiszesz go 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 Twoje motywy w pliku values-v21/styles.xml mogą je odziedziczyć. Oznacza to, że możesz uniknąć powielania stylów, zaczynając od motywu „podstawowego”, a następnie rozszerzając go o style specyficzne dla wersji.

Aby na przykład zadeklarować przejścia okienne w Androidzie 5.0 (poziom interfejsu API 21) i nowszych, musisz użyć nowych atrybutów. Twój motyw podstawowy w res/values/styles.xml może więc 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 dostosowane do 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 Udostępnianie zasobów alternatywnych.

Dostosowywanie stylów widżetów

Każdy element w ramach i w bibliotece wsparcia ma domyślny styl. Jeśli na przykład stylizujesz aplikację za pomocą motywu z Biblioteki pomocy, instancja Button zostanie oznaczona 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 w tym przykładzie zastosowano styl przycisku bez obramowania:

<Button
    style="@style/Widget.AppCompat.Button.Borderless"
    ... />

Jeśli chcesz zastosować ten styl do wszystkich przycisków, możesz go zadeklarować w swojej buttonStyle 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 samo jak rozszerzanie dowolnego innego stylu, a potem 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