布局

Windows Phone下的Silverlight提供了一种灵活的布局方式来指定控件在屏幕上的位置。此篇主要描述如何设计根据不同屏幕分辨率自动大小的用户界面。

 

主要包含以下内容

布局总览

绝对布局

动态布局

Panel控件

 

布局总览

Windows Phone下Silverlight的布局,是处理对象大小和位置的过程。给一个视觉元素布局,需要将其放入Panel控件或者其它容器控件中。Silverlight提供了一些Panel控件,比如Canvas,StackPanel和Grid,作为容器来定位和布置控件。

Windows Phone的Silverlight布局系统支持绝对和动态的布局。在绝对布局方式中,控件的定义通过类似x/y的坐标方式,比如Canvas。在动态布局方式中,用户界面根据屏幕的分辨率自动调整大小。

 

绝对布局

在绝对布局方式中,在布局面板中子元素通过指定其父元素中的位置坐标的形式来实现布局。绝对布局的方式并没有考虑到屏幕的大小。如果为了照顾到不同的屏幕分辨率,可以为其不同的屏幕分辨率单独的去设计不同的页面。

Windows Phone的Silverlight提供了Canvas来支持绝对方式的布局。默认情况下创建新Windows Phone程序项目的时候,根布局元素为Grid。如果要用绝对方式的布局,需要把Grid替换成Canvas。

在Canvas中布局,需要设置下面两个属性。在Visual Studio的设计视图中,当把控件拖拽到页面上的时候这两个属性就被更新了。

Canvas.Left

Canvas.Top

 

动态布局

在动态布局中,用户界面会根据屏幕分辨率的不同呈现不同的效果。子元素在父元素中通过指定如何布置和如何自动换行。比如,可以在面板中布置控件并且指定他们如何自定横向自动切换。要用到自动的或者根据比例的大小,需要设置其Height和Width属性。

设置Height和Width属性为Auto。当在Grid布局中使用这些值的时候,控件会填充满其容器。Auto属性在Grid和StackPanel中都是支持的。

对于包含文本的控件,不要设置其Height和Width属性,设置MinWidth和MinHeight属性。这样会避免出现文本内容由于容器大小问题而显示不全的情况。

如果要在Grid中按比例设置RowDefinition和ColumnDefinition,可以使用比例方式的Height和Width值。比如,如果要设置一个列是另一个列的五倍宽,可以分别对两列的ColumnDefinition属性的Width设置成*和5*。

Auto和星形符号调整大小

Auto用来让其填充满容器,即使内容的大小是可变的。星型模式用来根据比例分配Grid里的行和列。比如,如果有四个列,按照下面的设置其中的值。

Column_1

Auto-列会自动填满区域。

Column_2

*-列被分配完之后,这个列的宽度就是Column_4的一半。

Column_3

Auto-同Column_1

Column_4

2*-这个列的宽度会是列Column_2的一倍。

 

面板控件

Windows Phone的Silverlight下内置的面板有Canvas,StackPanel和Grid。

Canvas

Canvas使其内部的元素通过类似坐标的方式定位。Canvas适合用在包含的UI元素不需要移动或者改变的情况。

可以通过Canvas里控件的坐标来实现定位。这个坐标就是通过Canvas.Left和Canvas.Top来实现的。Canvas.Left通过设置对象距离Canvas容器左面边界的距离,Canvas.Top指定距离Canvas顶部边界的距离。

下面代码演示的是一个距离屏幕左端30像素,顶端200像素的矩形。

XAML

<Canvas Background="Transparent">

<Rectangle Canvas.Left="30" Canvas.Top="200"

Fill="red" Width="200" Height="200" />

</Canvas>

效果如下图:

clip_image001

Canvas这是一个画布面板(绝对布局),其子元素一般是依据Canvs的属性进行排布,也就是依赖属性,相当于x,y坐标,但是它是Canvas.Top,Canvas.Left表示。例如:

 
1
2
3
4
5
6
<Canvas>
    <Button Content="按钮" Canvas.Left="0" Canvas.Top="0"/>
    <Button Content="按钮" Canvas.Left="80" Canvas.Top="0"/>
    <Button Content="按钮" Canvas.Left="160" Canvas.Top="0"/>
    <Button Content="按钮" Canvas.Left="80" Canvas.Top="45"/>
</Canvas>

 

以上我们定义4个按钮,然后设置其Canvas.Top,Canvas.Left 属性,也就是y,x方向坐标,当然默认为0,0,得到如下所示:

 

StackPanel

StackPanel控件可以将其内部的元素以线性的方式横向或者纵向排布。通过Orientation属性指定子元素是以横向还是纵向排列,默认的属性为Vertical。

下面演示XAML的StackPanel子元素的纵向排列。

XAML

<StackPanel Margin="20">

<Rectangle Fill="Red" Width="50" Height="50" Margin="5" />

<Rectangle Fill="Blue" Width="50" Height="50" Margin="5" />

<Rectangle Fill="Green" Width="50" Height="50" Margin="5" />

<Rectangle Fill="Purple" Width="50" Height="50" Margin="5" />

</StackPanel>

运行效果如下图:

clip_image002

StackPanel 这是一个堆栈面板,其子元素一般是按照横排,或是竖排,放置,默认为竖排。可以设置Orientation属性

调整子元素排布方式。例如:

 
1
2
3
4
5
6
7
8
9
10
<StackPanel Orientation="Horizontal">
    <Button Content="按钮"/>
    <Button Content="按钮"/>
    <Button Content="按钮"/>
    <StackPanel>
        <Button Content="按钮"/>
        <Button Content="按钮"/>
        <Button Content="按钮"/>
    </StackPanel>
</StackPanel>

 

从上面可以知道:容器为:StackPanel,其子组件是横排列,其中一个组件又有子组件,里面内容默认是竖排列,因为StackPanel默认为竖排列方式。

结果如下:

 

Grid

Grid是最灵活的布局面板,支持多行和多列的方式布局。可以通过Grid.RowDefinitions和Grid.ColumnDefinitions属性来设置Grid里的行列信息。其内部的元素可以通过Grid.Column和Grid.Row属性定义定位到Grid的哪一行哪一列。内容也可以通过RowSpan和ColumnSpan的方式定义跨行和跨列。

Grid里的子元素根据XAML和代码的顺序依次显示在界面上,这样子元素就可以使用相同的坐标系统。可以参考ZIndex属性。

下面的XAML代码创建了一个三行两列的Grid。第一行和第三行的高度以撑满布局的方式填充,第二行的高度则分配成了剩余可用的高度。列的宽度是均分的。

XAML

<Grid ShowGridLines="True" Margin="12,0,12,0">

<Grid.RowDefinitions>

<RowDefinition Height="auto" />

<RowDefinition />

<RowDefinition Height="auto" />

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="*" />

<ColumnDefinition Width="*" />

</Grid.ColumnDefinitions>

<TextBox Text="1st row 1st column" TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" />

<TextBox Text="3rd row 1st column" TextWrapping="Wrap" Grid.Column="0" Grid.Row="2" />

<Button Content="1st row 3rd column" FontSize="17" Grid.Column="1" Grid.Row="0" />

<Button Content="3rd row 2nd column" FontSize="17" Grid.Column="1" Grid.Row="2" />

</Grid>

效果如下图所示:

clip_image003

Grid这是一个表格面板(相当于Table),其子元素一般是依据Grid指定的单元格布局,可以设定子元素为哪行哪列,也可以合并2个单元格,这与普通的Table是一样的。合并单元格的属性主要是: Grid.RowSpan="2"  Grid.ColumnSpan="2"  合并2行或者 2列。例如:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Grid>
<Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
</Grid.RowDefinitions>
 
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
 
<Button Content="按钮"/>
<Button Content="按钮" Grid.Row="1" Grid.Column="0" Background="Blue"/>
<Button Content="按钮" Grid.Column="1" Grid.RowSpan="2" Background="Gray"/>
<Button Content="按钮" Grid.Row="2" Grid.ColumnSpan="2" Background="Red"/>
</Grid>

以上定义3行2列的表格,默认的子组件位于一行一列,也就是Grid.Row="0" Grid.Column="0" ,它是以0为索引开始布局的。我们需要注意的是

Grid.RowSpan="2" Grid.ColumnSpan="2"  属性,它表示跨越2行,跨越2列的内容,显示结果为:

看见了吧,Grid是很有用处的。

以上就是主要的布局容器,可以作为顶层容器,也可以作为子容器,一般是不能被其他非容器包含的,但是有个东西除外,那就是Border,这个是边框,可以为容器设定一个边框,例如下面:

 
1
<Border  BorderThickness="10" BorderBrush="Yellow"> 容器</Border>

运行结果如下:

好了,就到这里,比较简单,但是如果能好好的利用这些布局容器以及组件,加上样式Style调优的话,你会布局出非常酷的界面,当然我们要以项目为基础,下面一节就开始我们的普通控件的简要介绍了,由于篇幅有限,我们一般只介绍普通用法,以及常用属性,方法等,需要了解更多更具体内容,可以参考官方资料。

 

如果对布局的需求比较复杂,并且Canvas, StackPanel和Grid都不能满足要求,可以尝试创建一个自定义的面板来实现子面板里的元素布局行为。具体的实现方法是继承Panel类并且重写其中的MeasureOverride和ArrangeOverride方法。

 

posted @ 2014-10-15 14:24  dodo-yufan  阅读(424)  评论(0编辑  收藏  举报