首页 > 代码库 > Windows Phone开发(12):认识一下独具个性的磁贴

Windows Phone开发(12):认识一下独具个性的磁贴

对“磁贴”的理解是一点也不抽象的,为什么呢?只要你愿意启动WP系统,无论你是在模拟器中还是在真机中,是的,桌面上那一块块像地板的玩意儿,就是磁贴了。
(图:磁贴)

技术分享

在上图中,我们很直观地看到磁贴图块的“真”面目,呵呵,其实很明显,这个设计真的很有个性,老实说,WP刚推出的时候,很多人说它这个那个的,其实这些人只过是起起哄罢了。
我是挺喜欢桌面上那一块块的图块的,这也是WP第一次给我留下的深刻印象,毕竟在安卓和IOS上,我们看到的都是传统手机的图标显示方式,而WP总让我觉得很有个性。

好的,看完了整体的,我们来看看局部的,好吗?别小看这些正方形的图块,里面可是大有文章的哦。不信?一起去瞧瞧。

磁贴的一个图块基本上由三个元素组成——背景图,标题文字以及计数器,嗯,当然了,图块最有意思的地方,就是它有正反两面。
下图为图块正反两面的元素组成结构图。
技术分享

 

=> 磁贴的分类。


磁贴分为应用程序磁贴和次要磁贴。
好不好理解呢?好,首先我们看看应用程序磁贴,它是指通过用户应用程序列表中长按应用程序来把应用程序固定到“开始”屏幕。
技术分享

 

那么,如何删除呢?在“开始”屏幕上找到你要移除的图块,长按,图块左上角会出现一个小图标,我们点击这小图标即可移除该磁贴。当然了,如果你想把移动到其它位置,在此时,你只需把图标拖到对应的位置,然后在桌面上随便点一下即可完成移动操作。
技术分享

 

次要磁贴就是相对于刚才的上面的应用程序磁贴而言的,它是由应用程序通过特定参数创建的,说直接一点嘛,就是通过我们开发者,用代码来创建的。

这个好比我们Windows桌面上的快捷方式,有的是直接指向可执行程序的,而有的是应用程序创建的,它后面带了命令行参数。举个例子吧,最典型的要数IE了,我经常上新浪微博,我希望在桌面上创建一个IE的快捷方式图标,双击运行IE的时候新打开新浪微博主页,那怎么做呢?请看下图。
技术分享

 

这样一来,你双击快捷方式启动IE就自动打开新浪微博首页。呵呵,次要磁贴也和这相类似。


=> 动手实战。

 
下面,我们一起来动手做一个稍微综合一点的例子,嗯,现在,你可以坐下来,先喝几口奶茶,然后启动VS,新建一个WP项目。
界面布局大致如下,你可以自由发挥。

技术分享

 

准备好两张美图,图片内容你喜欢,但要键康哦,尺寸为173*173像素,.jpg或.png都行,一张作为磁贴的正面背景,另一张作为磁贴的背面背景。
注意:把图片的生成操作改为“内容”。
技术分享

 

当然,为了方便大家练习参考,我把XAML贴出来,希望大家不要直接复制,而是认认真真的在VS里面输一遍,要多写代码多练习才会找到感觉的哦。

  1. <phone:PhoneApplicationPage   
  2.     x:Class="ShellTitleApp.MainPage"  
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  5.     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"  
  6.     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"  
  7.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  8.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  9.     mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"  
  10.     FontFamily="{StaticResource PhoneFontFamilyNormal}"  
  11.     FontSize="{StaticResource PhoneFontSizeNormal}"  
  12.     Foreground="{StaticResource PhoneForegroundBrush}"  
  13.     SupportedOrientations="Portrait" Orientation="Portrait"  
  14.     shell:SystemTray.IsVisible="True">  
  15.       
  16.     <phone:PhoneApplicationPage.Resources>  
  17.         <Style x:Key="textblStyle" TargetType="TextBlock">  
  18.             <Setter Property="FontSize" Value="http://www.mamicode.com/28"/>  
  19.             <Setter Property="Margin" Value="http://www.mamicode.com/0,12,5,6"/>  
  20.             <Setter Property="HorizontalAlignment" Value="http://www.mamicode.com/Right"/>  
  21.         </Style>  
  22.         <Style x:Key="textboxStyle" TargetType="TextBox">  
  23.             <Setter Property="FontSize" Value="http://www.mamicode.com/28"/>  
  24.             <Setter Property="Width" Value="http://www.mamicode.com/300"/>  
  25.             <Setter Property="Height" Value="http://www.mamicode.com/auto"/>  
  26.             <Setter Property="HorizontalAlignment" Value="http://www.mamicode.com/Left"/>  
  27.         </Style>  
  28.     </phone:PhoneApplicationPage.Resources>  
  29.   
  30.     <!--LayoutRoot 是包含所有页面内容的根网格-->  
  31.     <Grid x:Name="LayoutRoot" Background="Transparent">  
  32.         <Grid.RowDefinitions>  
  33.             <RowDefinition Height="Auto"/>  
  34.             <RowDefinition Height="*"/>  
  35.         </Grid.RowDefinitions>  
  36.   
  37.         <!--TitlePanel 包含应用程序的名称和页标题-->  
  38.         <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">  
  39.             <TextBlock x:Name="ApplicationTitle" Text="我的应用程序" Style="{StaticResource PhoneTextNormalStyle}"/>  
  40.             <TextBlock x:Name="PageTitle" Text="示例程序" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>  
  41.         </StackPanel>  
  42.   
  43.         <!--ContentPanel - 在此处放置其他内容-->  
  44.         <Grid x:Name="ContentPanel" Margin="0" Grid.Row="1">  
  45.             <Grid.RowDefinitions>  
  46.                 <RowDefinition Height="*" />  
  47.                 <RowDefinition Height="auto" />  
  48.             </Grid.RowDefinitions>  
  49.             <ScrollViewer HorizontalScrollBarVisibility="Auto" Grid.Row="0">  
  50.                 <Grid Margin="1">  
  51.                     <Grid.RowDefinitions>  
  52.                         <RowDefinition Height="auto"/>  
  53.                         <RowDefinition Height="auto"/>  
  54.                         <RowDefinition Height="auto"/>  
  55.                         <RowDefinition Height="auto"/>  
  56.                         <RowDefinition Height="auto"/>  
  57.                     </Grid.RowDefinitions>  
  58.                     <Grid.ColumnDefinitions>  
  59.                         <ColumnDefinition Width="auto"/>  
  60.                         <ColumnDefinition Width="*"/>  
  61.                     </Grid.ColumnDefinitions>  
  62.                     <TextBlock Grid.Row="0"  
  63.                                Grid.Column="0"  
  64.                                Text="正面标题:" Style="{StaticResource textblStyle}" />  
  65.                     <TextBox x:Name="txtForeTitle"  
  66.                              Style="{StaticResource textboxStyle}"  
  67.                              Grid.Row="0"  
  68.                              Grid.Column="1"/>  
  69.                     <TextBlock Text="计数器:" Style="{StaticResource textblStyle}"  
  70.                                Grid.Row="1"  
  71.                                Grid.Column="0"/>  
  72.                     <TextBox x:Name="txtCount"  
  73.                              Grid.Column="1"  
  74.                              Grid.Row="1" Style="{StaticResource textboxStyle}" >  
  75.                         <!--只允许输入数字-->  
  76.                         <TextBox.InputScope>  
  77.                             <InputScope >  
  78.                                 <InputScopeName NameValue="http://www.mamicode.com/Number"/>  
  79.                             </InputScope>  
  80.                         </TextBox.InputScope>  
  81.                     </TextBox>  
  82.                     <TextBlock Text="背面标题:"  
  83.                                Grid.Row="2"  
  84.                                Grid.Column="0" Style="{StaticResource textblStyle}" />  
  85.                     <TextBox x:Name="txtBackTitle"  
  86.                              Grid.Row="2"  
  87.                              Grid.Column="1" Style="{StaticResource textboxStyle}" />  
  88.                     <TextBlock Text="背景内容:"  
  89.                                Grid.Row="3"  
  90.                                Grid.Column="0" Style="{StaticResource textblStyle}" />  
  91.                     <TextBox x:Name="txtBackContent"  
  92.                              Grid.Row="3"  
  93.                              Grid.Column="1" Style="{StaticResource textboxStyle}" />  
  94.                     <!--提示是以何种方式启动-->  
  95.                     <CheckBox x:Name="chkStartType"  
  96.                               IsChecked="False"  
  97.                               Grid.Row="4"  
  98.                               Grid.Column="0"  
  99.                               Grid.ColumnSpan="2"  
  100.                               FontSize="30"  
  101.                               Content="通过应用程序创建的磁贴启动" IsEnabled="False" />  
  102.                 </Grid>  
  103.             </ScrollViewer>  
  104.             <StackPanel Grid.Row="1" Orientation="Horizontal">  
  105.                 <Button x:Name="btnAddToShellTitle"  
  106.                         Content="添加磁贴" Click="btnAddToShellTitle_Click" />  
  107.                 <Button x:Name="btnUpdateShellTitle"  
  108.                         Content="更新" Click="btnUpdateShellTitle_Click" />  
  109.                 <Button x:Name="btnDeleteShellTitle"  
  110.                         Content="删除" Click="btnDeleteShellTitle_Click" />  
  111.             </StackPanel>  
  112.         </Grid>  
  113.     </Grid>  
  114.    
  115.   
  116. </phone:PhoneApplicationPage>  


好的,最后,当然是把C#代码也写完。

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Windows;  
  6. using System.Windows.Controls;  
  7. using System.Windows.Documents;  
  8. using System.Windows.Input;  
  9. using System.Windows.Media;  
  10. using System.Windows.Media.Animation;  
  11. using System.Windows.Shapes;  
  12. using Microsoft.Phone.Controls;  
  13. using Microsoft.Phone.Shell;  
  14. using System.Windows.Threading;  
  15.   
  16. namespace ShellTitleApp  
  17. {  
  18.     public partial class MainPage : PhoneApplicationPage  
  19.     {  
  20.         // 要用的图片的相对路径  
  21.         private const string FORE_PIC = "images/a.png";  
  22.         private const string BACK_PIC = "images/b.png";  
  23.   
  24.         // 构造函数  
  25.         public MainPage()  
  26.         {  
  27.             InitializeComponent();  
  28.         }  
  29.   
  30.         protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)  
  31.         {  
  32.             base.OnNavigatedTo(e);  
  33.   
  34.             // 创建的磁贴的启动地址其实是指向 /MainPage.xaml?s=1  
  35.             // s=1参数是为了区别用户是不是通过程序所创建的磁贴来进入启动当前程序的,  
  36.             // 就像面前例子中讲到的把IE桌面快捷方式的参数指定为新浪微博的主页一个道理。  
  37.   
  38.             // 检测是否存在s=1来判断是否通过程序创建的磁贴来启动。  
  39.             ShellTile myTitle = ShellTile.ActiveTiles.FirstOrDefault(n => n.NavigationUri.ToString().Contains("s=1"));  
  40.             if (myTitle != null)  
  41.             {  
  42.                 this.chkStartType.IsChecked = true;  
  43.             }  
  44.             else  
  45.             {  
  46.                 this.chkStartType.IsChecked = false;  
  47.   
  48.             }  
  49.         }  
  50.   
  51.         // 创建图块  
  52.         private void btnAddToShellTitle_Click(object sender, RoutedEventArgs e)  
  53.         {  
  54.             // 不管我们的程序是否创建“开始”屏幕磁贴,ActiveTiles的第一个元素必是当前正在前台运行的  
  55.             // 应用程序。所以,在取出第一个ShellTile时,一定要通过判断是否存在s=1。  
  56.             // 这个s=1参数是随便取的。  
  57.             ShellTile myTitle = ShellTile.ActiveTiles.FirstOrDefault(m => m.NavigationUri.ToString().Contains("s=1"));  
  58.             // 如果已经创建就不建了。  
  59.             if (myTitle != null)  
  60.             {  
  61.                 MessageBox.Show("此应用程序的磁贴已经存在。");  
  62.             }  
  63.             else  
  64.             {  
  65.                 // 创建新磁贴  
  66.                 int Counter = 0;  
  67.                 // StandardTileData就是用来传递ShellTitle的属性参数的,  
  68.                 // 如正面背景图的URI,标题,计数器等。  
  69.                 StandardTileData myData = new StandardTileData()  
  70.                 {  
  71.                     Title = string.IsNullOrEmpty(txtForeTitle.Text) == true ? string.Empty : txtForeTitle.Text,  
  72.                     Count = int.TryParse(txtCount.Text, out Counter) == true ? Counter : 0,  
  73.                     BackTitle = string.IsNullOrEmpty(txtBackTitle.Text) == true ? string.Empty : txtBackTitle.Text,  
  74.                     BackContent = string.IsNullOrEmpty(txtBackContent.Text) == true ? string.Empty : txtBackContent.Text,  
  75.                     BackgroundImage = new Uri(FORE_PIC, UriKind.Relative),  
  76.                     BackBackgroundImage = new Uri(BACK_PIC, UriKind.Relative)  
  77.                 };  
  78.   
  79.                 // ShellTile.Create方法的第一个参数是我们启动应用程序时应该导航到哪里。  
  80.                 // 因为本示例主有一个页面,当然是导航到主页面,  
  81.                 // 因为是从我们创建的磁贴来启动的,所以不要忘了带上s=1参数。  
  82.                 ShellTile.Create(new Uri("/MainPage.xaml?s=1", UriKind.Relative), myData);  
  83.                 MessageBox.Show("磁贴图块创建成功。");  
  84.             }  
  85.         }  
  86.   
  87.         // 更新磁贴信息  
  88.         private void btnUpdateShellTitle_Click(object sender, RoutedEventArgs e)  
  89.         {  
  90.             // 同理,先要判断是否从我们创建的磁贴启动  
  91.             ShellTile myTitle = ShellTile.ActiveTiles.FirstOrDefault(m => m.NavigationUri.ToString().Contains("s=1"));  
  92.             if (myTitle != null)  
  93.             {  
  94.                 int Counter = 0;  
  95.                 StandardTileData data = new StandardTileData();  
  96.                 if (!string.IsNullOrEmpty(txtForeTitle.Text))  
  97.                 {  
  98.                     data.Title = txtForeTitle.Text;  
  99.                 }  
  100.                 if (int.TryParse(txtCount.Text,out Counter))  
  101.                 {  
  102.                     data.Count = Counter;  
  103.                 }  
  104.                 if (!string.IsNullOrEmpty(txtBackTitle.Text))  
  105.                 {  
  106.                     data.BackTitle = txtBackTitle.Text;  
  107.                 }  
  108.                 if (!string.IsNullOrEmpty(txtBackContent.Text))  
  109.                 {  
  110.                     data.BackContent = txtBackContent.Text;  
  111.                 }  
  112.                 myTitle.Update(data);  
  113.                 MessageBox.Show("磁贴数据更新完成。");  
  114.             }  
  115.   
  116.         }  
  117.   
  118.         // 删除磁贴  
  119.         // 注意:我们使用代码只可删除次要磁贴,也就是我们用代码创建的,  
  120.         // 不要去删除应用程序磁贴,即通过在应用程序项上长按创建的。  
  121.         private void btnDeleteShellTitle_Click(object sender, RoutedEventArgs e)  
  122.         {  
  123.             // 记着,要先判断是否找到通过我们代码创建的磁贴。  
  124.             ShellTile title = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("s=1"));  
  125.             if (title != null)  
  126.             {  
  127.                 title.Delete();  
  128.                 MessageBox.Show("磁贴图块删除成功。");  
  129.             }  
  130.         }  
  131.     }  
  132. }  


示例中我们重点是使用了ShellTile类,它并不复杂,成员不多,大家多玩几次就熟了。

运行之后,我们在“开始”屏幕中创建我们的磁贴,然后回到桌面,我们盯着它别动,你会发现,它的正面与反面会每隔几秒钟自动轮回切换。

Windows Phone开发(12):认识一下独具个性的磁贴