动手实验
2012年9月
优秀Windows应用商店应用的一个特点是适应不同尺寸的屏幕并处理横向模式和纵向模式之间的旋转。它还必须响应贴靠,贴靠允许两个应用程序共享屏幕和并排运行。
另一个与屏幕尺寸有关的特性是语义式缩放。不同于视觉缩放,它通过响应收缩手势等用户交互简单地对屏幕上的内容进行缩放,当用户放大或缩小时,语义式缩放对内容的呈现进行修改以显示或多或少的细节。
在本实验中,您将在实验1的基础上增加三个与Contoso Cookbook有关的重要用户界面。首先,当屏幕旋转时,您将对项-明细和组-明细页面的布局进行定制。接着,当应用程序被贴靠时,您将对项-明细页面进行定制。最后,您将在开始页面中实施语义式缩放并在单个屏幕上查看所有食谱组。
本实验将向您展示如何:
您需要下列软件完成本实验:
您必须执行以下步骤来准备本实验室的计算机:
本动手实验包含以下练习:
完成本实验的预计时间:40至60分钟。
Windows 8被设计在包括平板电脑和其它设备的多种设备上运行。通过板载传感器,这些设备知道它们是否在横向模式或纵向模式。一个在横向模式中显示良好的页面可能需要调整以在纵向模式中同样显示良好,并且反之亦然。
让我们从检查横向模式和纵向模式下的应用程序开始页面开始以决定是否需要任何修改。
1、在Visual Studio中打开您在实验1中创建的ContosoCookbook项目。如果您尚未完成实验1或希望从一个参考拷贝开始,您可以在开始材料中找到实验已完成的版本。
2、当设备在横向模式下,按F5在调试器中运行应用程序。如果使用模拟器,您将看到图1所示的食谱开始页面。
图1 横向模式下的开始页面
3、现在旋转设备至纵向模式。确认屏幕旋转90度,开始页面也将同时旋转,布局如图2所示。
注意:如果您在平板电脑上进行测试并且开始页面未旋转,可能是因为自动旋转未启用。一些设备具有锁定屏幕至当前方向的硬件开关。如果您有这样的设备,请确认开关设置在自动旋转模式。您也可以按Windows徽标键+O打开或关闭自动旋转。
如果您测试的硬件不支持方向改变,记住您可以使用Windows模拟器代替。单击模拟器右侧边缘的任一旋转按钮以旋转模拟器。
图2 纵向模式下的开始页面
4、得益于GridView控件对食谱项的呈现,开始页面在横向和纵向模式下均显示良好,因此这里不需要额外的工作。
5、返回Visual Studio并停止调试。
Contoso Cookbook应用包含三个页面:开始页面,组-明细页面和项-明细页面。开始页面不需要对纵向模式进行任何修改,因此让我们转向组-明细页面,即当您点击Chinese 或 Italian等某个组标题后出现的页面。
1、再次启动应用程序并点击Chinese以显示有关Chinese的组-明细页面。在横向模式,页面布局如图3所示。
图3 横向模式下的组-明细页面
2、现在旋转屏幕至纵向模式(见图4)。注意观察,呈现本页面大部分内容的GridView控件将组明细放置在组标题的右侧,并在屏幕的下半部分留下了很多空白。
图4 纵向模式下的组-明细页面
3、返回Visual Studio并停止调试。
4、打开GroupDetailPage.xaml并找到名称为“itemListView”的ListView控件。
5、紧随ListView控件后,添加另一个名称为“portraitListView”的ListView,它具有如下属性。
XAML
<!-- Vertical scrolling list only used in portrait mode --> <ListView x:Name="portraitListView" AutomationProperties.AutomationId="ItemListView" AutomationProperties.Name="Items In Group" TabIndex="1" Grid.Row="1" Visibility="Collapsed" Padding="86,0,20,60" ItemsSource="{Binding Source={StaticResource itemsViewSource}}" ItemTemplate="{StaticResource Standard500x130ItemTemplate}" SelectionMode="None" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"> <ListView.Header> <StackPanel> <Image Source="{Binding Image}" Margin="20,-10,18,0" MaxWidth="480" Stretch="UniformToFill" HorizontalAlignment="Left"/> <TextBlock Margin="20,20,18,30" Text="{Binding Description}" Style="{StaticResource BodyTextStyle}"/> </StackPanel> </ListView.Header> </ListView>
6、在GroupDetailPage.xaml中向下继续滚动并找到名称为“FullScreenPortrait”的VisualState元素。
7、在VisualState元素内,删除以下语句。
XAML
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Padding"> <DiscreteObjectKeyFrame KeyTime="0" Value="100,0,90,0"/> </ObjectAnimationUsingKeyFrames>
8、在刚删除的语句后添加以下语句。
XAML
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="portraitListView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames>
注意:您添加的ListView控件定义了如何在纵向模式下呈现食谱组。您添加的动画隐藏了纵向模式下的GridView控件并在视图状态变化至“FullScreenPortrait”时显示ListView。(Windows应用商店应用中的视图模型与ASP.NET视图状态无关,因此不要让该术语在脑海中产生歧义。)导致视图状态改变的事件之一是将设备从横向模型旋转至纵向或从纵向至横向。当应用程序被“贴靠”时视图状态也会发生改变。贴靠(辅屏)将在接下来的练习中讨论。
检测视图状态改变的代码被隐藏在基类中,应用程序的页面从该基类继承。LayoutAwarePage基类为主窗口的SizeChanged事件注册了一个处理程序并使用Windows运行时的VisualStateManager类来驱动一个视图状态到另一个视图状态的改变。
9、运行应用程序,点击Chinese以显示组-明细页面,并旋转设备至纵向模式。确认页面如图5所示。
图5 最终的纵向模式布局
10、返回Visual Studio并停止调试。
下一个任务是调整项-明细页面以在横向和纵向模式下同样能够有效使用空间并具备良好外观。
1、再次启动应用程序并点击某个食谱以显示项-明细页面。图6显示了页面在横向模式下的外观。
图6 横向模式下的项-明细页面
2、现在旋转设备进入纵向模式(图7)。在横向模式下工作良好的布局需要针对纵向模式进行一些调整。
图7 纵向模式下的项-明细页面
3、返回Visual Studio并停止调试。
4、打开ItemDetailPage.xaml并查找名称为“flipView”的FlipView。
5、在FlipView之后,添加另一个名称为“portraitFlipView”的控件。
XAML
<!-- FlipView used in portrait mode --> <FlipView x:Name="portraitFlipView" AutomationProperties.AutomationId="ItemsFlipView" AutomationProperties.Name="Item Details" Grid.Row="1" Margin="0,-3,20,0" ItemsSource="{Binding Source={StaticResource itemsViewSource}}" Visibility="Collapsed"> <FlipView.ItemTemplate> <DataTemplate> <UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates"> <ScrollViewer x:Name="scrollViewer" Style="{StaticResource VerticalScrollViewerStyle}" Grid.Row="1"> <!-- Vertical StackPanel for item-detail layout --> <StackPanel Orientation="Vertical" Margin="100,0,20,0"> <StackPanel Orientation="Vertical"> <TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Title}" TextWrapping="Wrap"/> <Image x:Name="image" Width="400" Margin="0,20,0,40" Stretch="Uniform" Source="{Binding Image}" HorizontalAlignment="Left"/> </StackPanel> <StackPanel Orientation="Vertical"> <TextBlock FontSize="26.667" FontWeight="Light" Text="Ingredients" Margin="0,0,0,16"/> <TextBlock FontSize="20" FontWeight="Light" LineHeight="32.5" Text="{Binding Ingredients, Converter={StaticResource ListConverter}}" TextWrapping="Wrap" /> </StackPanel> <StackPanel Orientation="Vertical"> <TextBlock FontSize="26.667" FontWeight="Light" Text="Directions" Margin="0,24,0,16"/> <ScrollViewer Style="{StaticResource VerticalScrollViewerStyle}"> <Grid> <TextBlock FontSize="20" FontWeight="Light" Text="{Binding Directions}" TextWrapping="Wrap" /> </Grid> </ScrollViewer> </StackPanel> </StackPanel> </ScrollViewer> </UserControl> </DataTemplate> </FlipView.ItemTemplate> </FlipView>
注意:在横向模式下,项-明细页面中的三个内容区域(食谱名称、图像和描述;原料以及指南)在一个多列Grid元素的列中进行布局,该Grid元素在名称为“flipView”的FlipView控件的数据模板中声明。您刚添加的FlipView控件针对纵向模式。它使用一个垂直的StackPanel元素在彼此的顶部堆叠内容区域。
6、在靠近ItemDetailPage.xaml的底部找到名称为“FullScreenPortrait” 的VisualState元素。(您需要的不是具有相同名称的嵌入在第一个FlipView控件中的VisualState元素)
7、在VisualState元素中的Storyboard元素中添加以下语句。当屏幕旋转至纵向模式时,这些语句将名称为“flipView”的控件切换为您刚添加的名称为“portraitFlipView”的控件。
XAML
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="flipView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="portraitFlipView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames>
8、启动应用程序并再次点击某个食谱以显示项-明细页面。旋转显示器至纵向模式并确认如图8所示的单列布局。
图8 修改后的纵向模式布局
9、旋转回横向模式并确认页面回到三列布局。
10、返回Visual Studio并停止调试。
贴靠允许Windows 8用户通过水平分割屏幕并排运行两个Windows应用商店应用。在触摸屏上,您可以通过从左侧边缘慢慢拖动手指穿过屏幕并到分割线(分割屏幕的垂直线条)出现时立即停止来演示贴靠。(如果您没有触摸屏,按Windows徽标键+句点键以贴靠应用程序。)图9显示了实际运行中的贴靠。Contoso Cookbook占据了屏幕左侧的320个像素,而Internet Explorer占据了剩余的部分。在此情况下Contoso Cookbook称为辅屏应用,Internet Explorer称为主屏应用。用户可以在屏幕上拖动分割线以对调应用程序的角色。
图9 实际运行中的贴靠
得益于Visual Studio为项目生成的包含在页面中的XAML代码,Contoso Cookbook已具备一些内置的贴靠行为。在本练习中,您将对其中一个页面进行简单的修改以改进用户的体验。
注意:为使贴靠运行,您必须在屏幕分辨率至少为1366 × 768像素的设备上运行Windows 8。Windows团队选择1366作为最低要求是因为它能为辅屏应用程序提供宽度为320像素(与很多智能手机的宽度相同)主应用提供宽度为1024像素的屏幕。分割线占据了余下的像素。如果您在低分辨率的屏幕上运行,请使用Windows模拟器完成本练习并选择分辨率至少为1366 × 768的模拟屏幕。
在本任务中您将查看应用程序被贴靠时Contoso Cookbook三个页面中每一个页面的运行情况。
1、按F5从Visual Studio启动应用程序。然后返回Windows开始屏幕并启动另一个应用程序,例如Internet Explorer。Internet Explorer现在占据整个屏幕,将手指放在屏幕的左侧边缘并缓慢向右拖动。当Contoso Cookbook出现在手指下,直到出现分割线后才停下。然后抬起手指以在当前位置贴靠Contoso Cookbook。
2、当Contoso Cookbook仅占据屏幕的一部分时,它的开始页面与全屏显示时的区别在哪里?
3、点击开始页面中的某个组名称以显示辅屏模式下的组-明细页面。它与全屏下的页面区别在哪里?
4、点击某个食谱以显示辅屏模式下的项-明细页面。页面的内容和布局与它在全屏下的区别在哪里?
5、返回Visual Studio并停止调试。
Visual Studio提供的缺省的辅屏布局是一个很好开始,但是您可以进一步对它们进行定制。在Contoso Cookbook中我们需要修改辅屏下的项-明细页面,因为缺省的布局在页面占据的部分屏幕上留下了很多空白。这些空间可以被用来显示食谱的更多信息。我们同时需要对 组-项页面(开始页面)和组-明细页面进行微调。先从组-项页面开始。
1、打开项目Common文件夹下的StandardStyles.xaml并找到名称为“Standard80ItemTemplate”的DataTemplate元素。
2、用下列内容替换DataTemplate:
XAML
<DataTemplate x:Key="Standard80ItemTemplate"> <Grid Margin="6"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="80"> <Image Source="{Binding Image}" Stretch="UniformToFill"/> </Border> <StackPanel Grid.Column="1" Margin="10,0,0,0"> <TextBlock Text="{Binding ShortTitle}" Style="{StaticResource ItemTextStyle}" MaxHeight="40"/> <StackPanel Orientation="Horizontal"> <TextBlock Text="Preparation time:" Style="{StaticResource CaptionTextStyle}" /> <TextBlock Text="{Binding PrepTime}" Style="{StaticResource CaptionTextStyle}" Margin="4,0,4,0" /> <TextBlock Text="minutes" Style="{StaticResource CaptionTextStyle}" /> </StackPanel> </StackPanel> </Grid> </DataTemplate>
3、按F5启动应用程序。
4、贴靠应用程序并确认它看上去如图10所示。
图10 修改后在辅屏视图下的组-项页面
5、返回Visual Studio并停止调试。
组-明细页面需要进行一些微调以改进布局。让我们进行修改并测试结果。
1、打开GroupDetailPage.xaml并找到名称为“itemListView”的ListView控件。
2、在控件的ListView.Header元素中删除第一个TextBlock元素。同时将图像以及剩下的TextBlock的左边距由20修改为10。以下是修改后的元素。
XAML
<ListView.Header> <StackPanel> <Image Source="{Binding Image}" Margin="10,0,18,0" MaxHeight="160" Stretch="UniformToFill"/> <TextBlock Margin="10,20,18,30" Text="{Binding Description}" Style="{StaticResource BodyTextStyle}"/> </StackPanel> </ListView.Header>
3、按F5以启动应用程序。
4、贴靠应用程序。单击French组标题并确认组-明细页面看上去如图11所示。
图11 修改后在辅屏视图下的组-明细页面
5、返回Visual Studio并停止调试。
最后的任务是修改辅屏下的项-明细页面以改进布局并包含食谱原料。
1、打开ItemDetailPage.xaml并在已有控件下添加以下FlipView控件。
XAML
<FlipView x:Name="snappedFlipView" AutomationProperties.AutomationId="ItemsFlipView" AutomationProperties.Name="Item Details" Grid.Row="1" Margin="0,-3,0,0" ItemsSource="{Binding Source={StaticResource itemsViewSource}}" Visibility="Collapsed"> <FlipView.ItemTemplate> <DataTemplate> <UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates"> <ScrollViewer x:Name="scrollViewer" Style="{StaticResource VerticalScrollViewerStyle}" Grid.Row="1"> <!-- Vertical StackPanel for item-detail layout --> <StackPanel Orientation="Vertical" Margin="20,0,20,0"> <StackPanel Orientation="Vertical"> <TextBlock FontSize="20" FontWeight="Light" Text="{Binding Title}" TextWrapping="Wrap"/> <Image x:Name="image" Width="260" Margin="0,12,0,40" Stretch="Uniform" Source="{Binding Image}" HorizontalAlignment="Left"/> </StackPanel> <StackPanel Orientation="Vertical"> <TextBlock FontSize="20" FontWeight="Light" Text="Ingredients" Margin="0,0,0,16"/> <TextBlock FontSize="16" FontWeight="Light" TextWrapping="Wrap" Text="{Binding Ingredients, Converter={StaticResource ListConverter}}" /> </StackPanel> </StackPanel> </ScrollViewer> </UserControl> </DataTemplate> </FlipView.ItemTemplate> </FlipView>
注意:这是您在项-明细页面中添加的第二个FlipView。另一个负责处理纵向模式下的布局。这个FlipView用于辅屏视图。
2、在ItemDetailPage.xaml底部附近找到名称为“Snapped”的VisualState元素。
3、在VisualState元素的Storyboard元素的已有元素中添加以下元素以在视图状态变为“Snapped”时隐藏缺省的FlipView并显示辅屏下的FlipView。
XAML
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="flipView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="snappedFlipView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames>
再次启动应用程序。贴靠应用程序使其在另一个应用程序旁占据屏幕的左侧。然后进入项-明细页面并确认辅屏页面现在显示食谱原料,如图12所示。
图12 修改后在辅屏视图下的项-明细页面
5、返回Visual Studio并停止调试。
很多运行在触摸屏上的应用程序允许用户使用两指缩放动作进行缩小和放大。例如图片编辑应用允许您在触摸屏幕的两指分开时放大图片,两指并拢时缩小图片。
大多数缩放是视觉缩放,这意味着它们仅仅对显示在屏幕上的内容进行缩放。将视觉缩放包含在应用程序中非常简单,但是Windows 8同时支持语义式缩放。
语义式缩放不仅仅缩放内容;它对内容分组以提供一个不同的语义视图。例如地图应用程序中的语义式缩放在用户放大时显示街道名称和楼宇名称等额外的细节,在用户缩小时删除这些细节。
为帮助您实现语义式缩放,Windows运行时中的Windows.UI.Xaml.Controls命名空间包含SemanticZoom控件。基本思路是由您向控件提供两个视图:放大视图和缩小视图,控件将响应用户的输入并在二者之间进行切换。您不必自己进行切换,当两指与屏幕接触后并拢或分开时,您不必编写响应手势识别的代码。如果您没有触摸屏,您可以通过按住Ctrl键并滚动鼠标滚轮的方法进行缩放;如果您没有鼠标,按住Ctrl键的同时按加号键或减号键进行放大或缩小。听起来很吸引人?让我们将语义式缩放投入使用。
将语义式缩放添加到Contoso Cookbook非常简单,您只需要声明一个SemanticZoom控件,并用开始页面中的放大和缩小视图来填充它即可。
1、打开GroupedItemsPage.xaml。
2、找到名称为“itemGridView”的GridView元素。删除它和它其中的所有内容。
3、用以下语句替换您刚删除的GridView。
XAML
<SemanticZoom Grid.Row="1"> <SemanticZoom.ZoomedInView> <!-- Horizontal scrolling grid used in most view states --> <GridView x:Name="itemGridView" AutomationProperties.AutomationId="ItemGridView" AutomationProperties.Name="Grouped Items" Margin="0,-3,0,0" Padding="116,0,40,46" ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}" ItemTemplate="{StaticResource Standard250x250ItemTemplate}" SelectionMode="None" IsItemClickEnabled="True" ItemClick="ItemView_ItemClick"> <GridView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Grid Margin="1,0,0,6"> <Button AutomationProperties.Name="Group Title" Content="{Binding Title}" Click="Header_Click" Style="{StaticResource TextButtonStyle}"/> </Grid> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> </GridView> </SemanticZoom.ZoomedInView> <SemanticZoom.ZoomedOutView> <GridView x:Name="groupGridView" Margin="116,0,40,46"> <GridView.ItemTemplate> <DataTemplate> <Grid Margin="0,0,24,0"> <Image Source="{Binding Group.GroupImage}" Width="250" Height="500" Stretch="UniformToFill" /> <TextBlock Text="{Binding Group.Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" FontSize="28" Margin="12"/> <TextBlock Text="{Binding Group.RecipesCount}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" FontSize="96" Margin="12,64,12,12" HorizontalAlignment="Right"/> </Grid> </DataTemplate> </GridView.ItemTemplate> </GridView> </SemanticZoom.ZoomedOutView> </SemanticZoom>
注意:您刚用包含两个GridView元素的SemanticZoom控件替换掉在开始页面呈现项目的GridView。两个GridView元素中的一个代表开始页面的放大视图,另一个代表缩小视图。SemanticZoom控件负责在两个视图之间切换。
4、在靠近GroupedItemsPage.xaml的底部找到名称为“Snapped”的VisualState元素并向该元素的Storyboard添加以下语句以在应用程序被贴靠时隐藏缩小视图。
XAML
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="groupGridView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/> </ObjectAnimationUsingKeyFrames>
5、打开GroupedItemsPage.xaml.cs并在LoadState方法结束处添加以下语句。
C#
this.groupGridView.ItemsSource = this.groupedItemsViewSource.View.CollectionGroups;
现在观察实际运行中的语义式缩放。
1、运行应用程序并确认您看到与之前一样的开始页面。
2、将两指放在屏幕上并并拢(或使用鼠标滚轮和Ctrl键)以缩小。确认页面变化为图13所示的页面。
图13 缩小的开始页面
3、再次将两指放在屏幕上,但是这次将两指彼此分开(或再次使用鼠标滚轮和Ctrl键)。开始页面发生了什么变化?
4、再次缩小并点击某个食谱组。确认您切换回放大视图并且视图被滚动至您选择的食谱组处。
5、返回Visual Studio并停止调试。
在本试验中,您对Contoso Cookbook的一些关键用户界面进行了加强。对旋转的显示器调整了布局,当应用程序被贴靠时定制了布局,并添加了语义式缩放以简化开始页面中食谱组的导航。您完成了所有上述工作但却编写了非常少的代码。
实验1和实验2涉及的大部分工作是创建用户体验:使页面在所有方向和模式下看起来不错。接下来将通过添加共享和搜索等支持进行一些后端工作。Contoso Cookbook将和Windows以及其它应用程序更加紧密地集成。