上一个篇博文说了WinPhone页面内部的东西,现在介绍表面的东西,先来看看一下一个WinPhone页面
这个页面分了三部分:顶部这个是状态栏,
中间这个是一个页面的内容部分,
最下面则是应用程序栏
本篇的页面解剖第一个要介绍的就最底下的应用程序栏,再去讲将中间页面内容的部分。
应用程序栏
说这个应用程序栏我就联想起其余两个系统的界面
在iOS中,由于只有”home”键,像Androd中的返回键,Menu键都没有了,所以类似的操作只能放到标题栏上面去,
这里除了放后退操作的按钮,还有其他功能按钮。回到WinPhone中,WinPhone没有标题栏搁这些按钮,所以WinPhone设立了ApplicationBar(应用程序栏),原本标题栏上面的一些按钮可以放到ApplicationBar上面。像这样
在Android中有Menu键,每个页面需要有更多的操作可以在Menu里获更多的功能选项
在WinPhone中解决这个问题的也是ApplicationBar,
那么现在说说这个ApplicationBar的建立,如果用XAML建立的话,可以使用以下的代码
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar Mode="Minimized">
<!--这里是Icon Buttonb部分-->
<shell:ApplicationBarIconButton IconUri="/Image/ApplicationBar.Check.png" Text="btn1"/>
<!--这里是Menu Item部分-->
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="Item1"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
ApplicationBar有几个比较有用的属性
- Mode:指定第一次显示在页面上时应用程序栏的大小:默认大小或最小大小。但是在支持横向的页面上,当为横向时,无论模式值如何,应用程序栏都使用默认大小显示,目的是提高可用性。
- Opacity:预期的值介于 0.0 和 1.0 之间。
- IsMenuEnabled:指示当用户扩展应用程序栏时是否可以看到菜单项。
- IsVisible:指示应用程序栏是否可见。
当然如果要让每个按钮点击之后又对应的事件处理,那就得加上Click事件。
如果用代码建立的话,那在页面构造函数中InitializeComponent()方法后加入下面的代码
ApplicationBar = new ApplicationBar();
ApplicationBarIconButton barIconBnt = new ApplicationBarIconButton();
barIconBnt.IconUri = new Uri("~/Image/ApplicationBar.Check.png", UriKind.Relative);
barIconBnt.Text = "barIconBnt";
ApplicationBar.Buttons.Add(barIconBnt); ApplicationBarMenuItem barMenuItm = new ApplicationBarMenuItem();
barMenuItm.Text = "barMenuItm";
ApplicationBar.MenuItems.Add(barMenuItm);
上面的代码中首先构造了一个新的ApplicationBar到ApplicationBar的属性中,后来加入了一个IconButton,后来再加了一个MenuItem,这些也是如控件设置的一般,既然是控件设置,那对ApplicationBar可以动态修改。
在设计ApplicationBar时,IconButton的数量个人认为不适宜多于4个,这不清楚在别的分辨率下是如何一种情况,但在我的WVGA下,多于4个就容纳不下了。如果在建立MenuItem时,文本的最大长度是14 到 20 个字符,不然会超出屏幕范围,而MenuItem的数量就不适宜多于4个,否则会会强制用户进行滚动。IconButton的图标的图片大小应为48x48像素,可与来自于C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons
页面布局
在设计一个页面设计时肯定会用到布局,在WinPhone中用到布局分了两大类:绝对布局和动态布局,而这两种布局用到的控件分别有以下三种Canvas(用于绝对布局),StackPanel(动态布局),Grid(动态布局)。下面再介绍两种布局以及三种控件。
绝对布局与Canvas
绝对布局则是以控件的左上角作为坐标原点,以Canvas控件的两个属性Left和Top来确定控件坐标位置,在新建一个普通页面之后可以把Content的Grid给删掉,更替成Canvas,再添加一个TextBlock和一个TextBox
<Canvas Name="ContentPanel" Grid.Row="1">
<TextBlock Text="TextBlock" Canvas.Left="23" Canvas.Top="25"/>
<TextBox Width="320" Canvas.Left="110"/>
</Canvas>
动态布局
感觉是除了绝对布局以外的所有布局都属于动态布局,对于Android而言,Android中的线性布局,网格布局都属于这里的动态布局,WinPhone的StackPanel则是线性布局,Grid则是网格布局。
Grid控件
Grid控件说是最灵活的布局面板,听了觉得有点黯然,Android的相对布局没有了,但WinPhone的Grid控件却比Android的TableLayout强大。在Grid中利用Grid.RowDefinitions和Grid.ColumnDefinitions定义面板中的行数和列数,例如
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
这里行的高度和列的宽度都有用到Auto和*,这两个值有不同的含义,Auto是指会根据内容的大小来调节这一行的行高多少或者这一列的列宽是多少;*号是指在计算完Auto之后控件的宽或高剩余的再去平均分,有多少个*就分多少份,上面的例子行只有一个*,假如多加2个<RowDefinition Height="*"/>,那么凡是带*号的行的行高则是除了Auto之后,再均分成3份,每份是1/3。*号前还可以带一个数字,表明这是原来的n倍,例如
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
这里有两个*号还有一个2*,那么在均分时就是分4份,前两个*分到的是一份,最后的2*分到的是两份。
StackPanel控件
这个控件则比较简单,与Android中的LinearLayout类似,他可以分水平排列和垂直排列两种,通过Orientation属性,枚举值也是只叫Vertial和Horizontal。例如
<StackPanel Name="ContentPanel" Grid.Row="1" Orientation="Vertical">
<Button Content="Button1" Width="Auto" Height="Auto"/>
<Button Content="Button2" />
<Button Content="Button3" />
</StackPanel>
假如把Orientation="Horizontal",效果则如下所示
在WinPhone的布局中还有几个比较有用 的属性
- Margin这个属性,它是控件与父容器相隔的距离,例如Margin="10,1,0,3"它分别表示Margin.Left=10,Margin.Top=1,Margin.Right=0,Margin.Botton=3的距离,其顺序就是左上右下一个圈;
- VerticalAlignment和HorizontalAlignment属性,它表示控件对于父控件的对齐方式。
页面的分类
利用VS来建立一个新的页面时都有三种选择,
像图中1里面的那种是空白页类型的,这种页面是最基础,在系统里面也能看见,一般在整个页面导航数中的叶子端,
这种页面在Xaml的定义中,把最根处的Grid分了两部分,一部分是一个StackPanel,它用来放置显示程序名称和页面名称的TextBlock。另一部分才是页面内容。
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions> <!--TitlePanel 包含应用程序的名称和页标题-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="我的应用程序" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="页面名称" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel> <!--ContentPanel - 在此处放置其他内容-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> </Grid>
</Grid>
Panorama页
第二个是Panorama页,这个中文叫全景页,在WinPhone8的照片应用,游戏都用了这类的页面,
它实际上是一个Panorama控件,在Xaml的定义中,它在根部的Grid中添加
<phone:Panorama Title="页面名称">
标签,Ttile属性则是本页面的名称,那么全景页中的每一项的定义如下面的形式
<phone:PanoramaItem Header="item1">
Hearder属性是定义项的名字,每个项的内容就在该标签下的Grid中定义,如
<phone:Panorama name Title="页面名称">
<phone:PanoramaItem Header="Panorama Item1">
<Grid>
<TextBlock Text="Text Content 1"/>
</Grid>
</phone:PanoramaItem>
<phone:PanoramaItem Header="Panorama Item2"> </phone:PanoramaItem>
</phone:Panorama>
如果需要在全景页面中添加背景图片,则需要在phone:Panorama节点下面添加以下代码
<phone:Panorama.Background>
<ImageBrush ImageSource="~/Image/ApplicationBar.Cancel.png"/>
</phone:Panorama.Background>
或者使用代码的形式
BitmapImage bitmapImage = new BitmapImage(new Uri(“~/Image/ApplicationBar.Cancel.png”,UriKind.Relative));
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = bitmapImage;
PanoControl.Background = imageBrush;
要引入的这幅图像分辨率应当在在 480 x 800 像素和 1024 x 800 像素(宽 x 高)之间
Pivot页
第三种是Pivot页,中文叫枢轴页,在WinPhone8中,设置,日历都是用了这种类型的页面
在Android和iOS的应用中有不少是用了选项卡布局,而在WinPhone中这类型的页面最适合顶替选项卡页面了,虽然上面的全景页也有类似的效果,但鄙人觉得还是枢轴页更适合。
它实际上用的是一个Pivot控件在Xaml的定义中,它在根部的Grid中添加
<phone:Pivot Title="页面名称">
同样Title是页面的名称了,枢轴的每一项都以下面的形式添加
<phone:PivotItem Header="Pivot1">
<Grid>
<TextBlock Text="Text Content 1"/>
</Grid>
</phone:PivotItem>
Header是每一项的标题,Grid里面自然是放置项的内容了。
使用枢轴页有几点要注意的
- 应用应该将 Pivot 页面数(4 页或更少)降到最低;
- Pivot 标头的高度是固定的,不能更改;
- 建议Pivot 标头文本限制为最多一个或两个单词。
还有两点是使用枢轴页和全景页都要注意的
- 绝对不要将 Pivot 控件放在其他 Pivot 控件内。绝对不要将 Pivot 控件放在某个 Panorama 控件内,不要在 Pivot 控件内部使用 Panorama 控件;
- 不要使用可在全景页和枢轴页内部平移或滚动的控件。