zoukankan      html  css  js  c++  java
  • 【Win10应用开发】自定义磁贴通知的排版

    前面老周用了两篇烂文,向大家介绍了Adaptive磁贴的模板使用。那些XML模板已经很强大了,不过,如果你觉得那些排版还不足以满足需求,不妨试试自己来定义磁贴的内容。

    其实,Runtime App支持在后台任务中生成XAML呈现,只要你编写的后台任务类从XamlRenderingBackgroundTask(位于Windows.UI.Xaml.Media.Imaging命名空间)类派生即可。利用这一特性,我们可以在后台生成XAML布局,然后通过RenderTargetBitmap类来呈现XAML内容,再把它保存为图片,最后把保存的图片作为磁贴的背景,就能达到自定义磁贴内容的功效了。

    第一步,在主应用程序项目中,添加一个XAML文件,因为这个文件不参与编译,也没有对应的Code hide文件,就单个XAML文件即可,实际上是一个文本文件。因此,在生成操作上要设置为“内容”,是否复制到输出目录,选择“不复制”,自定义工具不用填。如图

    然后你可以自己来设计排版,就和平时用XAML设计界面一样。

    <Border 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        BorderThickness="0">
        <Border.Background>
            <ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="UniformToFill" ImageSource="Assets/1.jpg" />
        </Border.Background>
    </Border>

    好了,我的界面就这样吧,简单好用。

    第二步,向解决方案添加一个Windows运行时组件项目,用来在其中定义后台任务类。代码如下:

        public sealed class UpdatetileTask : XamlRenderingBackgroundTask
        {
            protected override async void OnRun(IBackgroundTaskInstance taskInstance)
            { 
                   ……
             }
        }

    注意,这里和以前我们定义普通的后台任务不同,这一次不是实现后台任务接口,而是从XamlRenderingBackgroundTask类派生,然后重写OnRun方法。
    里面的处理和一般的后台任务一样了。

    1、先要从项目目录加载我们刚才自己定义的那个.xaml文件。

                Border root = new Border();
                Application.LoadComponent(root, new Uri("ms-appx:///customRender.xaml"));
                root.Width = 310;
                root.Height = 150;

    LoadComponent是Application类的一个静态方法,直接调用即可,第一个参数是要生成的可视化对象的实例,第二个参数是XAML文件的URI。

    我们声明的可视化对象的类型一定要与XAML文档中的根节点的类型匹配,上面在定义XAML文档时,根节点是Border,因此这里声明的变量类型必须为Border,LoadComponent方法调用后,会自动加载并编译XAML文档,然后填充Border变量。

    为了让可视化对象能够呈现到位图中,记住要显示设置它的高度和宽度,因为默认情况下Width和Height都为0

    2、呈现XAML对象到位图。

                // 将XAML对象呈现到图像中
                RenderTargetBitmap rtb = new RenderTargetBitmap();
                // 因为示例是为宽磁贴生成背景图片的
                // 所以目标的图像大小与宽磁贴相同即可
                // 310 x 150
                await rtb.RenderAsync(root, 310, 150);
                // 取出图像数据
                IBuffer bfData = await rtb.GetPixelsAsync();
                // 将其转换为字节数组
                byte[] data = bfData.ToArray();


    3、在本地目录中创建新的PNG文件,并把呈现的XAML内容编码到图像文件中。

                // 在本地目录中创建新的PNG图像文件
                StorageFolder localfd = ApplicationData.Current.LocalFolder;
                StorageFile pngFile = await localfd.CreateFileAsync("bg.png", CreationCollisionOption.ReplaceExisting);
                // 打开文件流
                using (IRandomAccessStream stream = (await pngFile.OpenAsync(FileAccessMode.ReadWrite)))
                {
                    // 创建PNG图像编码器
                    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                    // 设置图像数据
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight, 72d, 72d, data);
                    await encoder.FlushAsync();
                }

    4、文件保存后,可以用ms-appdata:///local/开头的URI来访问文件。这时候,我们可以生成磁贴通知的XML文档,并更新磁贴。

                // 组创XML文档
                string xml = "<tile>" +
                                "<visual>" +
                                    "<binding template="TileWide">" +
                                        "<image src="ms-appdata:///local/bg.png" placement="background" />" +
                                    "</binding>"   +
                                 "</visual>" +
                             "</tile>";
                // 创建XML文档
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xml);
                // 更新磁贴通知
                TileNotification notification = new TileNotification(doc);
                TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
                updater.Update(notification);

    第三步,在主应用程序中引用刚才的后台任务项目。然后配置一下清单文件,在正式版的SDK中,已经可以使用图形化的清单编辑器了,可以直接操作。

    添加一个后台任务声明,类型为“常规”。

    填上后台任务类的入口点,即类名,要包括命名空间的名字。

    第四步,在前台代码中注册后台任务。前面的文章中,老周给大家介绍过可以通ApplicationTrigger直接在应用程序中触发后台任务,所以本示例我就用它了。

                var res = await BackgroundExecutionManager.RequestAccessAsync();
                if (res == BackgroundAccessStatus.Denied || res == BackgroundAccessStatus.Unspecified)
                {
                    Debug.WriteLine("后台任务被禁用。"); return;
                }
    
                // 考虑注册后台任务
                BackgroundTaskRegistration reg = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME) as BackgroundTaskRegistration;
    
                if (reg == null)
                {
                    BackgroundTaskBuilder bd = new BackgroundTaskBuilder();
                    bd.Name = TASK_NAME;
                    bd.TaskEntryPoint = typeof(backUpdater.UpdatetileTask).FullName;
                    ApplicationTrigger trigger = new ApplicationTrigger();
                    bd.SetTrigger(trigger);
                    reg = bd.Register();
                }

    最后,我们可以在代码中手动触发这个后台。

                BackgroundTaskRegistration reg = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME) as BackgroundTaskRegistration;
                if (reg == null)
                {
                    return;
                }
    
                ApplicationTrigger trigger = reg.Trigger as ApplicationTrigger;
                await trigger.RequestAsync();

    运行应用程序后,把程序固定到开始屏幕,并把图标改为宽磁贴,然后回到应用程序,触发后台,更新磁贴。

    唉,天天写代码很枯燥,很无聊?没事,一起来坐在桃花底下读读《西厢记》,就会好的了。

    OK,今天的牛皮暂时吹到这里。

    例子源代码下载:http://files.cnblogs.com/files/tcjiaan/customTileUpdateApp.zip

  • 相关阅读:
    android webView使用
    Android开发者必知的开发资源(转载)
    Android中的消息推送(转载)
    Android消息处理系统——Looper、Handler、Thread(转载)
    Android之单元测试学习(转载)
    ndroid获得Bitmap的三种方法(转载)
    Android性能调优(转载)
    Android的开机流程(转载)
    Android命名规范(自定义)(转载)
    无法解决 equal to 操作中 Latin1_General_CI_AI 和 Chinese_PRC
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4711455.html
Copyright © 2011-2022 走看看