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 sekcji Utwórz

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

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

Motyw to zbiór atrybutów zastosowanych do całej aplikacji, działania lub hierarchii widoków, a nie tylko do pojedynczego widoku. Gdy zastosujesz motyw, każdy widok w aplikacji lub aktywności będzie korzystał z wszystkich obsługiwanych atrybutów 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 ma 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 są pod wieloma względami podobne, ale służą do różnych celów. Motywy i style mają tę samą podstawową strukturę – para 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 korzystanie z nich i utrzymywanie ich w wielu widżetach.

Motyw określa zbiór nazwanych zasobów, do których można się odwoływać za pomocą stylów, układów, widżetów itp. Motywy przypisują do zasobów Androida nazwy semantyczne, np. colorPrimary.

Style i motywy muszą ze sobą współdziałać. Możesz np. używać stylu, w którym 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” motywu na „ciemny” i zmienić wartości wszystkich nazw zasobów. Nie musisz zmieniać stylów, ponieważ style używają nazw semantycznych, a nie konkretnych definicji kolorów.

Więcej informacji o współdziałaniu motywów i stylów znajdziesz na blogu w poście na temat stylu 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 nazwie, która jednoznacznie identyfikuje styl.
  2. Dodaj element <item> dla każdego atrybutu stylu, który chcesz zdefiniować. Element name w każdym produkcie określa atrybut, którego używasz w swoim układzie jako atrybut XML. Wartość w elemencie <item> jest wartością tego atrybutu.

Załóżmy np., że zdefiniujesz taki styl:

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

Możesz zastosować styl do widoku w ten sposób:

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

Każdy atrybut określony w stylu jest stosowany do danego widoku, o ile go zaakceptuje. Widok danych ignoruje wszystkie atrybuty, których nie akceptuje.

Jednak zamiast stosować styl do poszczególnych widoków, zwykle stosujesz je jako motyw dla całej aplikacji, aktywności lub kolekcji widoków danych, tak jak to 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, za pomocą atrybutu parent określ styl, który chcesz rozszerzyć. Potem możesz 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 ten sposób:

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

Pamiętaj jednak, aby zawsze dziedziczyć podstawowe style aplikacji z Biblioteki pomocy na Androida. Style w Bibliotece pomocy zapewniają zgodność, optymalizując każdy styl pod kątem atrybutów interfejsu użytkownika dostępnych w każdej wersji. Style z Biblioteki pomocy często mają nazwę podobną do stylu z platformy, ale zawierają 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. W tym przykładzie przedstawiono dziedziczenie stylów wyglądu tekstu z biblioteki pomocy:

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

Zamiast używać atrybutu parent, możesz też dziedziczyć style (poza tymi z platformy) przez rozszerzenie nazwy stylu o notację kropkową. To znaczy, że przed nazwą stylu umieść nazwę stylu, który chcesz odziedziczyć, oddzieloną kropką. 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 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 je dalej dziedziczyć, dowolną liczbę razy, łącząc kolejne nazwy.

Aby dowiedzieć się, które atrybuty możesz zadeklarować za pomocą tagu <item>, zajrzyj do tabeli „Atrybuty XML” w opisach klas. Wszystkie widoki obsługują atrybuty XML z klasy podstawowej View, a wiele z nich ma własne atrybuty specjalne. Na przykład atrybuty XML TextView zawierają atrybut android:inputType, który możesz zastosować do widoku tekstu otrzymującego dane wejściowe, np. widżetu EditText.

Stosowanie stylu jako motywu

Motyw możesz utworzyć w taki sam sposób, w jaki tworzysz style. Różnica polega na tym, jak go stosować: zamiast stylu z atrybutem style w widoku danych, zastosuj motyw z atrybutem android:theme w tagu <application> lub tagu <activity> w pliku AndroidManifest.xml.

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

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

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 korzysta ze stylów, które obsługuje, spośród stylów zdefiniowanych 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.

Począwszy od Androida 5.0 (poziom interfejsu API 21) i Biblioteki pomocy Androida w wersji 22.1 możesz też określić atrybut android:theme dla widoku w pliku układu. Spowoduje to zmianę motywu tego widoku oraz wszystkich widoków podrzędnych, co przydaje się przy zmianie palet kolorów motywów w określonej części interfejsu.

Poprzednie przykłady pokazują, jak zastosować motyw, np. Theme.AppCompat z Biblioteki pomocy Androida. Zwykle jednak warto dostosować motyw, aby pasował do marki aplikacji. Najlepszym sposobem, aby to zrobić, 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 ustawiania atrybutów w swojej aplikacji na Androida. Możesz np. ustawić atrybuty bezpośrednio w układzie, zastosować styl w widoku danych, zastosować motyw do układu, a nawet automatycznie ustawić atrybuty.

Wybierając styl aplikacji, zwróć uwagę na hierarchię stylów Androida. Ogólnie rzecz biorąc, aby uzyskać spójność, używaj motywów i stylów. Jeśli podasz te same atrybuty w wielu miejscach, z listy poniżej dowiesz się, które atrybuty zostaną ostatecznie zastosowane. Lista jest uporządkowana od najwyższego priorytetu do najniższego.

  1. Stosowanie stylów na poziomie znaków lub akapitu za pomocą rozpiętości tekstu do klas wyodrębnionych za pomocą TextView.
  2. Automatyczne stosowanie atrybutów.
  3. Stosowanie poszczególnych atrybutów bezpośrednio w widoku.
  4. Stosuję styl do widoku.
  5. Styl domyślny.
  6. Zastosowanie motywu do zbioru widoków danych, aktywności lub całej aplikacji.
  7. stosowanie pewnych stylów właściwych dla widoku, np. ustawianie TextAppearance w elemencie TextView;

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

Wygląd tekstu

Ograniczenie dotyczące stylów polega na tym, że można zastosować tylko jeden styl do elementu View. W elemencie TextView możesz jednak też 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 umożliwia definiowanie stylów tekstowych, a styl elementu 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 TextAppearance.

TextAppearance obsługuje podzbiór atrybutów stylu dostępnych w usłudze TextView. Pełną listę atrybutów znajdziesz tutaj: 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 akapitu, dlatego 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 Twojej aplikacji motyw Material Design, zgodnie z definicją w pliku styles.xml projektu. Ten styl AppTheme rozszerza motyw z Biblioteki pomocy i obejmuje zastąpienia atrybutów kolorów używanych 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 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, które zostały zdefiniowane w pliku res/values/colors.xml projektu. To ten plik, który edytujesz, aby zmienić kolory. Zapoznaj się z opisem kolorów Material Design, aby zwiększyć wygodę użytkowników dzięki dynamicznym kolorom i dodatkowym niestandardowym kolorom.

Gdy poznasz już kolory, zaktualizuj wartości w polu 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. Gdy dodajesz style widoków w układzie, możesz też znaleźć atrybuty, patrząc na tabelę „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 określonych typach widoków danych, a niektóre mają zastosowanie do wszystkich widoków. Jednak niektóre atrybuty motywu (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 określa animację przejścia po rozpoczęciu aktywności. Więcej informacji znajdziesz w artykule Rozpoczynanie działania przy użyciu animacji.

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

W bibliotece pomocy są też inne motywy, które możesz rozszerzyć zamiast tych z poprzedniego przykładu. Najlepiej zobaczyć dostępne motywy w pliku themes.xml biblioteki.

Dodawanie stylów zależnie 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 starymi wersjami. Potrzebujesz tylko kolejnego pliku styles.xml zapisanego 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 dla wszystkich wersji, więc motywy w values-v21/styles.xml mogą je dziedziczyć. Dzięki temu można uniknąć duplikowania stylów, rozpoczynając od motywu „podstawowego”, a następnie rozszerzając go w stylach danej wersji.

Aby na przykład zadeklarować przejście okna na Androida 5.0 (poziom interfejsu API 21) lub nowszego, musisz użyć nowych atrybutów. 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 związane z konkretną wersją 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ć styl AppTheme w pliku manifestu, a system wybierze style dostępne dla każdej wersji systemu.

Więcej informacji o korzystaniu z alternatywnych zasobów dla różnych urządzeń znajdziesz w artykule na temat udostępniania alternatywnych zasobów.

Dostosuj style widżetów

Każdy widżet w platformie i Bibliotece pomocy ma domyślny styl. Jeśli na przykład dostosujesz styl aplikacji przy użyciu motywu z biblioteki pomocy, styl instancji Button będzie stosowany 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 tak wygląda styl przycisku biblioteki bez obramowania:

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

Jeśli chcesz zastosować ten styl do wszystkich przycisków, możesz zadeklarować go w elemencie 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 rozszerzając każdy inny styl, a następnie zastosować własny styl widżetu w układzie lub motywie.

Dodatkowe materiały

Aby dowiedzieć się więcej o motywach i stylach, zapoznaj się z tymi dodatkowymi zasobami:

Posty na blogu