Style i motywy

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak korzystać z motywów w funkcji Utwórz

Style i motywy na Androidzie pozwalają oddzielić szczegóły projektu aplikacji od struktury i działania interfejsu, podobnie jak w przypadku arkuszy stylów w projektowaniu stron internetowych.

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

Motyw to zbiór atrybutów zastosowanych do całej aplikacji, aktywności lub hierarchii widoków, 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, np. paska stanu czy tła okna.

Style i motywy są deklarowane w pliku zasobów stylu w res/values/, który zwykle nosi nazwę styles.xml.

Rysunek 1. Do tej samej aktywności zastosowano 2 motywy: 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 konkretnego typu widoku. Jeden styl może np. określać atrybuty przycisku. Każdy atrybut określony w stylu to atrybut, który można ustawić w pliku układu. Wyodrębnienie wszystkich atrybutów do stylu ułatwia ich używanie i przechowywanie w wielu widżetach.

theme definiuje zbiór nazwanych zasobów, do których mogą się odwoływać style, układy, widżety itd. Motywy przypisują do zasobów Androida nazwy semantyczne (np. colorPrimary).

Style i motywy powinny ze sobą współpracować. Możesz np. mieć styl określający, że jedna część przycisku to colorPrimary, a inna – colorSecondary. Rzeczywiste definicje tych kolorów są podane w motywie. Gdy urządzenie przejdzie w tryb nocny, aplikacja może przełączyć się z jasnego na ciemny motyw, zmieniając wartości wszystkich nazw zasobów. Nie musisz zmieniać stylów, ponieważ korzystają one z 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.

Utwórz i zastosuj styl

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> jest wartością 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>

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 zaakceptuje. Widok ignoruje wszystkie atrybuty, które nie są akceptowane.

Jednak zamiast stosować styl do poszczególnych widoków, zwykle stosujesz style jako motyw do całej aplikacji, aktywności lub kolekcji widoków, jak opisano w innej sekcji tego przewodnika.

Rozszerzanie i dostosowywanie stylu

Tworząc własne style, zawsze rozszerzaj istniejący styl z platformy lub biblioteki pomocy, aby zachować zgodność ze stylami interfejsu platformy. Aby rozszerzyć styl, określ go 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 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>

Zawsze dziedzicz jednak podstawowe style aplikacji z biblioteki pomocy Androida. 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 z Biblioteki pomocy często mają nazwę podobną do stylu z tej platformy, ale zawierają dodatkowo atrybut AppCompat.

Aby dziedziczyć style z biblioteki lub własnego projektu, zadeklaruj nazwę stylu nadrzędnego bez części @android:style/ widocznej 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 tych z platformy – przez rozszerzenie nazwy stylu za pomocą notacji kropkowej, zamiast używania atrybutu parent. Oznacza to, że przed nazwą stylu umieść oddzieloną kropką nazwę stylu, który chcesz odziedziczyć. Zwykle robi się to tylko przy rozszerzaniu 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 dalej dziedziczyć takie style dowolną liczbę razy, łączą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 ma 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 tym, że zamiast stosować do widoku styl z atrybutem style, stosujesz motyw z atrybutem android:theme do tagu <application> lub <activity> w pliku AndroidManifest.xml.

Oto jak zastosować „ciemny” motyw Material Design w bibliotece pomocy Androida do całej aplikacji:

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

Oto jak zastosować „jasny” motyw tylko do jednej aktywności:

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

Każdy widok w aplikacji lub działaniu stosuje obsługiwane przez niego style spośród tych zdefiniowanych w podanym 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.

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 zmianę motywu tego widoku oraz widoków podrzędnych, co jest przydatne przy zmianie palety kolorów motywów w określonej części interfejsu.

Poprzednie przykłady pokazują, jak zastosować motyw taki jak Theme.AppCompat, który pochodzi z Biblioteki pomocy Androida. Zwykle wolisz jednak dostosować motyw, aby pasował do marki aplikacji. Najlepszym sposobem jest rozszerzenie tych stylów z Biblioteki pomocy i zastąpienie niektórych atrybutów w sposób opisany w następnej sekcji.

Hierarchia stylów

Android oferuje wiele sposobów konfigurowania atrybutów w aplikacji na Androida. Możesz na przykład ustawiać atrybuty bezpośrednio w układzie, zastosować styl do widoku, zastosować motyw do układu, a nawet automatycznie ustawiać atrybuty.

Przy wyborze stylu aplikacji pamiętaj o hierarchii stylów Androida. Ogólnie rzecz biorąc, aby uzyskać spójność, używaj jak najczęściej motywów i stylów. Jeśli podasz te same atrybuty w wielu miejscach, ta lista określa, które z nich zostaną ostatecznie zastosowane. Lista jest uporządkowana od najwyższego do najniższego.

  1. Stosowanie stylu na poziomie znaków lub akapitu z wykorzystaniem rozpiętości tekstu w klasach pochodzących z funkcji TextView.
  2. Automatyczne stosowanie atrybutów
  3. Stosowanie poszczególnych atrybutów bezpośrednio w widoku danych.
  4. Stosuję styl do widoku.
  5. Styl domyślny.
  6. Zastosowanie motywu do kolekcji widoków danych, aktywności lub całej aplikacji.
  7. Zastosowanie określonego stylu zależnego od widoku danych, np. ustawienia TextAppearance w elemencie TextView.

Rysunek 2. Styl z span zastępuje styl z textAppearance.

Wygląd tekstu

Ograniczeniem stylów jest to, że do elementu View możesz zastosować tylko 1 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 określenie stylu tekstu, a styl View jest dostępny do innych zastosowań. Pamiętaj jednak, że jeśli zdefiniujesz atrybuty tekstowe bezpośrednio w elemencie View lub w stylu, wartości te zastąpią wartości z pola TextAppearance.

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

Niektóre typowe atrybuty TextView, które nie zostały uwzględnione, 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 stosowany jest do aplikacji motyw Material Design, zgodnie z definicją w pliku styles.xml projektu. Ten styl AppTheme rozszerza motyw z biblioteki pomocy i zawiera zastąpienia atrybutów koloru, 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ć projekt kolorów aplikacji, aktualizują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 są w rzeczywistości odwołaniami do innych zasobów kolorów, które są zdefiniowane w pliku res/values/colors.xml projektu. To właśnie 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 znasz już 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 następnie zastąpić dowolne inne style. Możesz na przykład zmienić kolor tła działania 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 swoim 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 do określonych typów widoków, a niektóre do wszystkich. 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 sekcji Rozpoczynanie aktywności przy użyciu animacji.

Biblioteka pomocy Androida zawiera też inne atrybuty, których można użyć do dostosowania motywu rozszerzonego od Theme.AppCompat, takie jak atrybut colorPrimary widoczny w poprzednim przykładzie. Najlepiej wyświetlić je w pliku attrs.xml biblioteki.

W Bibliotece pomocy są też dostępne inne motywy, które możesz chcieć rozszerzyć, zamiast korzystać z motywów pokazanych w poprzednim przykładzie. Dostępne motywy znajdziesz w pliku themes.xml biblioteki.

Dodaj style zależnie od 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. Potrzebny jest tylko kolejny plik styles.xml zapisany w katalogu values zawierającym 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 o style właściwe dla danej wersji.

Aby na przykład zadeklarować przejścia w oknach w przypadku Androida 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.

Aby dowiedzieć się więcej o korzystaniu z alternatywnych zasobów na różnych urządzeniach, przeczytaj artykuł Udostępnianie alternatywnych zasobów.

Dostosuj style widżetów

Każdy widżet w platformie i w bibliotece pomocy ma styl domyślny. 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ć do przycisku inny styl widżetu, możesz użyć atrybutu style w pliku układu. Na przykład w ten sposób zastosowano 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 rozszerzać każdy inny styl, a następnie zastosować styl widżetu niestandardowego w układzie lub motywie.

Dodatkowe materiały

Więcej informacji o motywach i stylach znajdziesz w tych dodatkowych materiałach:

Posty na blogu