Поделиться через


Динамические стили в Xamarin.Forms

Стили не реагируют на изменения свойств и остаются неизменными в течение длительности приложения. Например, после назначения стиля визуальному элементу, если один из экземпляров Setter изменен, удален или добавлен новый экземпляр Setter, изменения не будут применены к визуальному элементу. Однако приложения могут динамически реагировать на изменения стиля во время выполнения с помощью динамических ресурсов.

DynamicResource Расширение разметки аналогично StaticResource расширению разметки в том, что оба используют ключ словаря для получения значения изResourceDictionary. Однако при выполнении StaticResource одного поиска словаря DynamicResource сохраняется ссылка на ключ словаря. Поэтому при замене записи словаря, связанной с ключом, изменение применяется к визуальному элементу. Это позволяет вносить изменения стиля среды выполнения в приложение.

В следующем примере кода показаны динамические стили на странице XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DynamicStylesPage" Title="Dynamic" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
              ...
            </Style>
            <Style x:Key="blueSearchBarStyle"
                   TargetType="SearchBar"
                   BasedOn="{StaticResource baseStyle}">
              ...
            </Style>
            <Style x:Key="greenSearchBarStyle"
                   TargetType="SearchBar">
              ...
            </Style>
            ...
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <SearchBar Placeholder="These SearchBar controls"
                       Style="{DynamicResource searchBarStyle}" />
            ...
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Экземпляры SearchBar используют расширение разметки для ссылки на именованный searchBarStyleDynamicResource Style объект, который не определен в XAML. Однако, поскольку Style свойства SearchBar экземпляров задаются с помощью DynamicResourceключа, отсутствующий ключ словаря не приводит к возникновению исключения.

Вместо этого в файле программной части конструктор создает ResourceDictionary запись с ключом searchBarStyle, как показано в следующем примере кода:

public partial class DynamicStylesPage : ContentPage
{
    bool originalStyle = true;

    public DynamicStylesPage ()
    {
        InitializeComponent ();
        Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
    }

    void OnButtonClicked (object sender, EventArgs e)
    {
        if (originalStyle) {
            Resources ["searchBarStyle"] = Resources ["greenSearchBarStyle"];
            originalStyle = false;
        } else {
            Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
            originalStyle = true;
        }
    }
}

При выполнении searchBarStyle обработчика OnButtonClicked событий переключится между blueSearchBarStyle иgreenSearchBarStyle. Результат показан на следующих снимках экрана:

Пример динамического стиля синего цветаПример зеленого динамического стиля

В следующем примере кода показана эквивалентная страница в C#:

public class DynamicStylesPageCS : ContentPage
{
    bool originalStyle = true;

    public DynamicStylesPageCS ()
    {
        ...
        var baseStyle = new Style (typeof(View)) {
            ...
        };
        var blueSearchBarStyle = new Style (typeof(SearchBar)) {
            ...
        };
        var greenSearchBarStyle = new Style (typeof(SearchBar)) {
            ...
        };
        ...
        var searchBar1 = new SearchBar { Placeholder = "These SearchBar controls" };
        searchBar1.SetDynamicResource (VisualElement.StyleProperty, "searchBarStyle");
        ...
        Resources = new ResourceDictionary ();
        Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
        Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
        Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];

        Content = new StackLayout {
            Children = { searchBar1, searchBar2, searchBar3, searchBar4,    button    }
        };
    }
    ...
}

В C# SearchBar экземпляры используют SetDynamicResource метод для ссылки searchBarStyle. Код OnButtonClicked обработчика событий идентичен примеру XAML и при выполнении searchBarStyle переключится между blueSearchBarStyle и greenSearchBarStyle.

Наследование динамического стиля

Производный стиль от динамического стиля не может быть достигнут с помощью Style.BasedOn свойства. Вместо этого Style класс включает BaseResourceKey свойство, которое можно задать для ключа словаря, значение которого может динамически измениться.

В следующем примере кода показано наследование динамического стиля на странице XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DynamicStylesInheritancePage" Title="Dynamic Inheritance" IconImageSource="xaml.png">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="baseStyle" TargetType="View">
              ...
            </Style>
            <Style x:Key="blueSearchBarStyle" TargetType="SearchBar" BasedOn="{StaticResource baseStyle}">
              ...
            </Style>
            <Style x:Key="greenSearchBarStyle" TargetType="SearchBar">
              ...
            </Style>
            <Style x:Key="tealSearchBarStyle" TargetType="SearchBar" BaseResourceKey="searchBarStyle">
              ...
            </Style>
            ...
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <SearchBar Text="These SearchBar controls" Style="{StaticResource tealSearchBarStyle}" />
            ...
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Экземпляры SearchBar используют StaticResource расширение разметки для ссылки на именованный tealSearchBarStyleStyle объект. При этом Style задаются некоторые дополнительные свойства и используется BaseResourceKey свойство для ссылки searchBarStyle. DynamicResource Расширение разметки не требуется, так как tealSearchBarStyle не изменится, за исключением Style производных от него расширений. tealSearchBarStyle Поэтому сохраняет ссылку на searchBarStyle и изменяется при изменении базового стиля.

В файле программной части конструктор создает ResourceDictionary запись с ключом searchBarStyle, как показано в предыдущем примере, демонстрирующем динамические стили. При выполнении searchBarStyle обработчика OnButtonClicked событий переключится между blueSearchBarStyle иgreenSearchBarStyle. Результат показан на следующих снимках экрана:

Пример наследования динамического стиля синим цветомПример наследования зеленого динамического стиля

В следующем примере кода показана эквивалентная страница в C#:

public class DynamicStylesInheritancePageCS : ContentPage
{
    bool originalStyle = true;

    public DynamicStylesInheritancePageCS ()
    {
        ...
        var baseStyle = new Style (typeof(View)) {
            ...
        };
        var blueSearchBarStyle = new Style (typeof(SearchBar)) {
            ...
        };
        var greenSearchBarStyle = new Style (typeof(SearchBar)) {
            ...
        };
        var tealSearchBarStyle = new Style (typeof(SearchBar)) {
            BaseResourceKey = "searchBarStyle",
            ...
        };
        ...
        Resources = new ResourceDictionary ();
        Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
        Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
        Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];

        Content = new StackLayout {
            Children = {
                new SearchBar { Text = "These SearchBar controls", Style = tealSearchBarStyle },
                ...
            }
        };
    }
    ...
}

Он tealSearchBarStyle назначается непосредственно свойству Style SearchBar экземпляров. При этом Style задаются некоторые дополнительные свойства и используется BaseResourceKey свойство для ссылки searchBarStyle. Этот SetDynamicResource метод не требуется, так как tealSearchBarStyle он не изменится, за исключением Style производных от него. tealSearchBarStyle Поэтому сохраняет ссылку на searchBarStyle и изменяется при изменении базового стиля.

Другие видео о Xamarin см. на Channel 9 и YouTube.