【WP8】换肤功能的实现

主题功能在移动开发中是最常见的功能之一,用的最多的是日间模式和夜间模式的切换,下面说说如何在WP上使用主题,不同主题的差别无非就是两种(颜色和图片),在WP上我们通常使用资源来设置颜色,系统提供了两种背景(白色/黑色)和主题色,当用户为系统设置不同的背景和主题色的时候,App也会根据主题色的不同而展示不同的效果,所以我们使用改变Brush的颜色或背景来控制主题的显示

  1、修改颜色画刷

    在修改原有的画刷(PhoneAccentBrush,PhoneForegroundBrush,PhoneBackgroundBrush等等)

    http://msdn.microsoft.com/zh-cn/library/ff769552 这里是系统默认的画刷

    例如:把主题色改为红色

    //把主题色改为红色(由于SolidColorBrush的Color是依赖属性,所以该修改可以通知到所有绑定该画刷的Brush)
    ((SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"]).Color = Colors.Red;    
    
    //注意:ResourceDictionary没有为setter提供实现,所以不能通过下面方式对Resources进行修改,会抛出NotImplementedException异常
    //Application.Current.Resources["PhoneAccentBrush"] = new SolidColorBrush(Colors.Red);

  2、修改(添加)图片画刷

    例如:添加一个图片画刷资源

        //构造图片BitmapImage
        var bitmapImage = new BitmapImage();
        bitmapImage.SetSource(Application.GetResourceStream(
            new Uri("Assets/ThemeResources/Day/black.jpg", UriKind.Relative)).Stream);

        if (Application.Current.Resources.Contains("MainBackgroundImageBrush"))
        {
            //如果已经定义过了MainBackgroundImageBrush,则设置其ImageSource
            //建议在App.cs或者其资源引用文件中定义MainBackgroundImageBrush,这样在引用的地方可以看到智能提示,减少拼写错误
            ((ImageBrush) Application.Current.Resources["MainBackgroundImageBrush"]).ImageSource = bitmapImage;
        }
        else
        {
            //如果没有该资源,则添加(注意:这里需要在页面加载前设置,否则绑定不到该资源,一般放在App.xaml.cs的构造函数中)
            Application.Current.Resources.Add("MainBackgroundImageBrush", new ImageBrush {ImageSource = bitmapImage});
        }

  App.xaml

        <Application
            x:Class="ThemeDemo.App"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">

            <!--Application Resources-->
            <Application.Resources>
                <local:LocalizedStrings xmlns:local="clr-namespace:ThemeDemo" x:Key="LocalizedStrings"/>
                
                <!--如果不是系统画刷,在这里进行定义,在引用的地方可以得到智能感知-->
                <ImageBrush x:Name="MainBackGroundBrush"></ImageBrush>
                
            </Application.Resources>

            <Application.ApplicationLifetimeObjects>
                <!--Required object that handles lifetime events for the application-->
                <shell:PhoneApplicationService
                    Launching="Application_Launching" Closing="Application_Closing"
                    Activated="Application_Activated" Deactivated="Application_Deactivated"/>
            </Application.ApplicationLifetimeObjects>

        </Application>

 

 

看完修改资源画刷的方法,下面我们封装一个ThemeManager对主题进行管理

  本来打算使用XML文件来保存主题颜色和图片信息(QQ貌似用XML保存的),但是XML对颜色和图片路径没有智能感知,所以在定义画刷颜色的时候不够直观,在纯文本的XML中写容易出错,所以下面使用xaml来定义资源文件,WP上的系统主题资源也是使用xaml文件定义的,VS对xaml文件有很好的支持,下面定义两个主题文件(DayResource.xaml, NightResource.xml)

 

DayResources.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!--背景色-->
    <Color x:Key="PhoneBackgroundBrush">White</Color>
    <!--前景色-->
    <Color x:Key="PhoneForegroundBrush">#FF000000</Color>
    <!--次标题颜色-->
    <Color x:Key="PhoneSubtleBrush">#DD000000</Color>

    <!--主背景图-->
    <BitmapImage x:Key="MainBackGroundBrush" UriSource="/Assets/ThemeResources/Day/Blue.jpg"/>
</ResourceDictionary>

 

NightResources.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!--背景色-->
    <Color x:Key="PhoneBackgroundBrush">Black</Color>
    <!--前景色-->
    <Color x:Key="PhoneForegroundBrush">#FFDDDDDD</Color>
    <!--次标题颜色-->
    <Color x:Key="PhoneSubtleBrush">#DDDDDDDD</Color>

    <!--主背景图-->
    <BitmapImage x:Key="MainBackGroundBrush" UriSource="/Assets/ThemeResources/Night/Black.jpg"/>
</ResourceDictionary>

 

接下来我们在ThemeManager加载主题资源

/// <summary>
/// 主题管理器
/// </summary>
public class ThemeManager
{
    /// <summary>
    /// 加载主题资源
    /// </summary>
    /// <param name="path">例如:/Assets/ThemeResources/DayResource.xaml</param>
    public static void Load(string path)
    {
        var resourceDictionary = new ResourceDictionary();

        //从程序集读取资源(这里的Uri格式:/解决方案;component/资源文件路径)
        Application.LoadComponent(resourceDictionary,
            new Uri(string.Format("/ThemeDemo;component{0}", path), UriKind.Relative));

        //应用样式(只有颜色和Color和图片BitmapImage)
        foreach (DictionaryEntry kv in resourceDictionary)
        {
            if (kv.Value is Color)
            {
                ((SolidColorBrush)Application.Current.Resources[kv.Key]).Color = (Color)kv.Value;
            }
            else if (kv.Value is BitmapImage)
            {
                if (Application.Current.Resources.Contains(kv.Key))
                {
                    ((ImageBrush)Application.Current.Resources[kv.Key]).ImageSource = ((BitmapImage)kv.Value);
                }
                else
                {
                    Application.Current.Resources.Add(kv.Key, new ImageBrush {ImageSource = (BitmapImage) kv.Value});
                }
            }
        }
    }
}

 

Toolkit都定义好了,下面是使用,我们在App.xaml.cs的构造函数中加载默认主题,当我们需要修改主题的时候,直接调用ThemeManager的Load方法就可以直接切换主题了

下面是效果图(背景图拿QQ的)

 如果需要添加其他主题,直接编写Resource.xaml即可,在需要应用的时候传主题路径

 

附上Demo:

https://files.cnblogs.com/bomo/ThemeDemo.zip

 

声明:转载请注明出处http://www.cnblogs.com/bomo/

posted @ 2014-07-27 23:04  bomo  阅读(1178)  评论(1编辑  收藏  举报