Xamarin Forms - 主题制作简单





5.00/5 (7投票s)
本文假设您对C#、XAML样式和Xamarin Forms有基本了解,并展示了如何使用简单的样式来实现主题设置。
引言
最近,我们为一位客户开始使用Xamarin Forms构建一个移动应用程序,以同时支持iOS和Android设备。我们需要考虑的一个设计方面是如何为应用程序设置不同的主题颜色方案。
我们为主题设置设定了以下设计目标:
所有UI元素都应支持主题设置,并能实时更改主题。
由于我们的开发人员来自Web技术背景,对Xamarin Forms还不熟悉,因此主题设置应该易于实现且在技术上保持一致。
应使用XAML样式而不是级联样式表(CSS),因为CSS在Xamarin Forms中尚未成熟。
本文假设您对C#、XAML样式和Xamarin Forms有基本了解,并展示了如何使用简单的样式来实现主题设置。
先决条件
您需要最新版本的Visual Studio 2017,并安装了Xamarin工作负载和模拟器。
步骤 1 – 创建一个新的Xamarin Forms项目
让我们开始使用Visual Studio 2017创建一个新的Xamarin Forms项目,并选择文件-->新建-->项目。
在“新建项目”窗口中,选择跨平台-->移动应用(Xamarin Forms),如下图所示:
将项目名称输入为主题演示,然后单击确定。将显示以下选项对话框:
在上图中,选择空白项目,然后单击确定,将创建以下项目。
选择模拟器并运行项目,您应该能看到带有欢迎文本的主页,如下所示:
步骤 2 – 创建XAML样式
在共享项目中,创建一个名为“Themes”的新文件夹,并添加一个名为“Default.xaml”的新XAML样式,如下图所示:
添加文件后,打开Default.xaml.cs文件,并将“ContentPage
”替换为“ResourceDictionary
”,如下所示:
using Xamarin.Forms;
namespace ThemingDemo.Themes
{
public partial class Default: ResourceDictionary
{
public Default ()
{
InitializeComponent ();
}
}
}
打开Default.xaml文件,并将全部内容替换为以下样式:
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.Themes.Default">
<!--Implicit Styles-->
<Style TargetType="Label" BaseResourceKey="BodyStyle">
<Setter Property="HorizontalOptions" Value="StartAndExpand" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#AF3800" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium" />
</Style>
<Style TargetType="Switch">
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BackgroundColor" Value="White" />
</Style>
<!--Explicit Styles - a Key is Added - Must be referred by Style="{DynamicResource MainStackLayout}" -->
<Style x:Key="MainStackLayout" TargetType="StackLayout" >
<Setter Property="Padding">
<Setter.Value>
<OnPlatform x:TypeArguments="Thickness" Android="8, 8, 8, 8" iOS="10, 10, 10, 10"/>
</Setter.Value>
</Setter>
<Setter Property="VerticalOptions" Value="StartAndExpand" />
<Setter Property="Spacing" Value="5" />
</Style>
<Style TargetType="Label" x:Key="LabelPageHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Label" BaseResourceKey="SubtitleStyle" x:Key="LabelSubHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#AF3800" />
</Style>
<Style TargetType="Button" x:Key="ButtonSecondary">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#aa2029" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium"/>
</Style>
</ResourceDictionary>
请注意,在上一个文件中,我们使用XAML创建了一些隐式样式(Implicit Styles)和显式样式(Explicit Styles)。有关使用XAML样式设置Xamarin Forms应用程序主题的详细信息,请在此处查找。
我们希望为应用程序提供两种不同的主题。因此,让我们创建一个名为“Pink.xaml”的新XAML样式。我们通过复制Default.xaml并将其重命名为“Pink.xaml”来创建此样式。之后,我们仅将颜色方案更改为粉红色
。
“Pink.xaml”的修改内容如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.Themes.Pink">
<!--Implicit Styles-->
<Style TargetType="Label" BaseResourceKey="BodyStyle">
<Setter Property="HorizontalOptions" Value="StartAndExpand" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#FF1493" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium" />
</Style>
<Style TargetType="Switch">
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BackgroundColor" Value="White" />
</Style>
<!--Explicit Styles - a Key is Added - Must be referred by Style="{DynamicResource MainStackLayout}" -->
<Style x:Key="MainStackLayout" TargetType="StackLayout" >
<Setter Property="Padding">
<Setter.Value>
<OnPlatform x:TypeArguments="Thickness" Android="8, 8, 8, 8" iOS="10, 10, 10, 10"/>
</Setter.Value>
</Setter>
<Setter Property="VerticalOptions" Value="StartAndExpand" />
<Setter Property="Spacing" Value="5" />
</Style>
<Style TargetType="Label" BaseResourceKey="TitleStyle" x:Key="LabelPageHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Label" BaseResourceKey="SubtitleStyle" x:Key="LabelSubHeading">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Medium" />
<Setter Property="TextColor" Value="#FF1493" />
</Style>
<Style TargetType="Button" x:Key="ButtonSecondary">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderRadius" Value="15" />
<Setter Property="BackgroundColor" Value="#e24fd1" />
<Setter Property="TextColor" Value="White" />
<Setter Property="FontSize" Value="Medium"/>
</Style>
</ResourceDictionary>
现在,“Themes”目录如下所示:
步骤 3 – 创建主题管理器助手
创建一个名为ThemeManager
的新助手类,并添加一个签名如下的public
方法ChangeTheme
:
using System;
using Xamarin.Forms;
namespace ThemingDemo.Themes
{
public class ThemeManager
{
public static void ChangeTheme(string themeName)
{
Application.Current.Resources.Clear();
Application.Current.Resources.MergedDictionaries.Clear();
var type = typeof(ThemeManager);
var uri = $"{type.Assembly.GetName().Name}.Themes.{themeName}";
var theme = Type.GetType(uri);
Application.Current.Resources.MergedWith = theme;
}
}
}
上面的代码将清除现有样式,并根据主题名称添加新样式。
步骤 4 – 使用XAML创建登录内容页面
为了进行主题设置示例,我们将向MainPage.xaml添加两个输入字段(用户名
和密码
)以及一个登录按钮和一个选择主题的Picker控件。
从Picker控件中选择主题将改变登录页面(主页面)的主题。
现在,让我们打开MainPage.xaml并按如下方式修改XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.MainPage">
<StackLayout Style="{DynamicResource MainStackLayout}">
<Label Text="Login" Style="{DynamicResource LabelPageHeading}"/>
<Label Text="Welcome to Theming Demo" Style="{DynamicResource LabelSubHeading}"/>
<Label Text="Username"/>
<Entry Placeholder="Username"/>
<Label Text="Password" />
<Entry IsPassword="true" Placeholder="Password"/>
<StackLayout Orientation="Horizontal">
<Switch HorizontalOptions="Start" />
<Label Text="Remember me"/>
</StackLayout>
<Button Text="SignIn"/>
<Button Text="Forgot Password?" Style="{DynamicResource ButtonSecondary}"/>
<StackLayout Orientation="Horizontal">
<Label Text="Theme: " VerticalOptions="Center" />
<Picker x:Name="themePicker" Title="Select a theme" HorizontalOptions="Start">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Default</x:String>
<x:String>Pink</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
</StackLayout>
</StackLayout>
</ContentPage>
在上面的XAML中,请注意我们为某些控件使用了Style
属性应用了显式样式。对于Entry
和Button
等控件,我们没有应用任何显式样式,因此它们将使用隐式样式。
对于Picker
,我们设置了Items Source为“Default
”和“Pink
”,这与Style文件的名称相同。
现在,让我们打开MainPage.xaml.cs并按如下方式修改C#:
using System;
using ThemingDemo.Themes;
using Xamarin.Forms;
namespace ThemingDemo
{
public partial class MainPage: ContentPage
{
public MainPage()
{
InitializeComponent();
themePicker.SelectedIndexChanged += ThemePicker_SelectedIndexChanged;
}
private void ThemePicker_SelectedIndexChanged(object sender, EventArgs e)
{
ThemeManager.ChangeTheme(themePicker.SelectedItem.ToString());
}
}
}
步骤 5 – 初始化默认样式
我们已经完成了在主题选择时动态更改主题的大部分步骤。但是,当应用程序运行时,我们将初始化默认主题,这在App.xaml.cs文件中完成,如下所示:
using ThemingDemo.Themes;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace ThemingDemo
{
public partial class App: Application
{
public App()
{
InitializeComponent();
ThemeManager.ChangeTheme("Default”); //Initialize the Default Theme
MainPage = new MainPage();
}
}
}
步骤 6 – 运行项目并测试
我们已经完成了基本的主题实现,现在是时候进行测试了。让我们通过定位可用的模拟器来运行项目,您应该会看到如下的登录屏幕。请注意,应用程序使用了我们在Default.xaml样式文件中创建的默认主题。
现在,单击“主题选择器”,您应该会看到以下对话框:
现在选择“Pink
”样式,屏幕颜色方案将自动更改为粉红色
,如下所示:
关注点
我们已经了解了如何使用XAML样式创建隐式和显式样式,并动态应用它们来更改外观和感觉。
最近,Xamarin Forms也引入了级联样式表(CSS),可以使用CSS标准创建样式。更多信息可以在这里找到。目前,使用XAML样式可以实现的所有样式设置都无法通过CSS实现,并且有一个bug阻止我使用CSS动态更改主题。因此,本文主要关注XAML样式。
历史
- 2019年2月22日 – 初始版本