天天看點

布局

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>

效果如下圖:

布局

Canvas這是一個畫布面闆(絕對布局),其子元素一般是依據Canvs的屬性進行排布,也就是依賴屬性,相當于x,y坐标,但是它是Canvas.Top,Canvas.Left表示。例如:

1

2

3

4

5

6

<code>&lt;</code><code>Canvas</code><code>&gt;</code>

<code>   </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Canvas.Left</code><code>=</code><code>"0"</code> <code>Canvas.Top</code><code>=</code><code>"0"</code><code>/&gt;</code>

<code>   </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Canvas.Left</code><code>=</code><code>"80"</code> <code>Canvas.Top</code><code>=</code><code>"0"</code><code>/&gt;</code>

<code>   </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Canvas.Left</code><code>=</code><code>"160"</code> <code>Canvas.Top</code><code>=</code><code>"0"</code><code>/&gt;</code>

<code>   </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Canvas.Left</code><code>=</code><code>"80"</code> <code>Canvas.Top</code><code>=</code><code>"45"</code><code>/&gt;</code>

<code>&lt;/</code><code>Canvas</code><code>&gt;</code>

以上我們定義4個按鈕,然後設定其Canvas.Top,Canvas.Left 屬性,也就是y,x方向坐标,當然預設為0,0,得到如下所示:

布局

StackPanel

StackPanel控件可以将其内部的元素以線性的方式橫向或者縱向排布。通過Orientation屬性指定子元素是以橫向還是縱向排列,預設的屬性為Vertical。

下面示範XAML的StackPanel子元素的縱向排列。

&lt;StackPanel Margin="20"&gt;

&lt;Rectangle Fill="Red" Width="50" Height="50" Margin="5" /&gt;

&lt;Rectangle Fill="Blue" Width="50" Height="50" Margin="5" /&gt;

&lt;Rectangle Fill="Green" Width="50" Height="50" Margin="5" /&gt;

&lt;Rectangle Fill="Purple" Width="50" Height="50" Margin="5" /&gt;

&lt;/StackPanel&gt;

運作效果如下圖:

布局

StackPanel 這是一個堆棧面闆,其子元素一般是按照橫排,或是豎排,放置,預設為豎排。可以設定Orientation屬性

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

7

8

9

10

<code>&lt;</code><code>StackPanel</code> <code>Orientation</code><code>=</code><code>"Horizontal"</code><code>&gt;</code>

<code>   </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code><code>/&gt;</code>

<code>   </code><code>&lt;</code><code>StackPanel</code><code>&gt;</code>

<code>       </code><code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code><code>/&gt;</code>

<code>   </code><code>&lt;/</code><code>StackPanel</code><code>&gt;</code>

<code>&lt;/</code><code>StackPanel</code><code>&gt;</code>

從上面可以知道:容器為:StackPanel,其子元件是橫排列,其中一個元件又有子元件,裡面内容預設是豎排列,因為StackPanel預設為豎排列方式。

結果如下:

布局

Grid

Grid是最靈活的布局面闆,支援多行和多列的方式布局。可以通過Grid.RowDefinitions和Grid.ColumnDefinitions屬性來設定Grid裡的行列資訊。其内部的元素可以通過Grid.Column和Grid.Row屬性定義定位到Grid的哪一行哪一列。内容也可以通過RowSpan和ColumnSpan的方式定義跨行和跨列。

Grid裡的子元素根據XAML和代碼的順序依次顯示在界面上,這樣子元素就可以使用相同的坐标系統。可以參考ZIndex屬性。

下面的XAML代碼建立了一個三行兩列的Grid。第一行和第三行的高度以撐滿布局的方式填充,第二行的高度則配置設定成了剩餘可用的高度。列的寬度是均分的。

&lt;Grid ShowGridLines="True" Margin="12,0,12,0"&gt;

&lt;Grid.RowDefinitions&gt;

&lt;RowDefinition Height="auto" /&gt;

&lt;RowDefinition /&gt;

&lt;/Grid.RowDefinitions&gt;

&lt;Grid.ColumnDefinitions&gt;

&lt;ColumnDefinition Width="*" /&gt;

&lt;/Grid.ColumnDefinitions&gt;

&lt;TextBox Text="1st row 1st column" TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" /&gt;

&lt;TextBox Text="3rd row 1st column" TextWrapping="Wrap" Grid.Column="0" Grid.Row="2" /&gt;

&lt;Button Content="1st row 3rd column" FontSize="17" Grid.Column="1" Grid.Row="0" /&gt;

&lt;Button Content="3rd row 2nd column" FontSize="17" Grid.Column="1" Grid.Row="2" /&gt;

&lt;/Grid&gt;

效果如下圖所示:

布局

Grid這是一個表格面闆(相當于Table),其子元素一般是依據Grid指定的單元格布局,可以設定子元素為哪行哪列,也可以合并2個單元格,這與普通的Table是一樣的。合并單元格的屬性主要是: Grid.RowSpan="2"  Grid.ColumnSpan="2"  合并2行或者 2列。例如:

11

12

13

14

15

16

17

<code>&lt;</code><code>Grid</code><code>&gt;</code>

<code>&lt;</code><code>Grid.RowDefinitions</code><code>&gt;</code>

<code>   </code><code>&lt;</code><code>RowDefinition</code> <code>Height</code><code>=</code><code>"*"</code><code>/&gt;</code>

<code>&lt;/</code><code>Grid.RowDefinitions</code><code>&gt;</code>

<code>&lt;</code><code>Grid.ColumnDefinitions</code><code>&gt;</code>

<code>   </code><code>&lt;</code><code>ColumnDefinition</code> <code>Width</code><code>=</code><code>"*"</code><code>/&gt;</code>

<code>&lt;/</code><code>Grid.ColumnDefinitions</code><code>&gt;</code>

<code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code><code>/&gt;</code>

<code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Grid.Row</code><code>=</code><code>"1"</code> <code>Grid.Column</code><code>=</code><code>"0"</code> <code>Background</code><code>=</code><code>"Blue"</code><code>/&gt;</code>

<code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Grid.Column</code><code>=</code><code>"1"</code> <code>Grid.RowSpan</code><code>=</code><code>"2"</code> <code>Background</code><code>=</code><code>"Gray"</code><code>/&gt;</code>

<code>&lt;</code><code>Button</code> <code>Content</code><code>=</code><code>"按鈕"</code> <code>Grid.Row</code><code>=</code><code>"2"</code> <code>Grid.ColumnSpan</code><code>=</code><code>"2"</code> <code>Background</code><code>=</code><code>"Red"</code><code>/&gt;</code>

<code>&lt;/</code><code>Grid</code><code>&gt;</code>

以上定義3行2列的表格,預設的子元件位于一行一列,也就是Grid.Row="0" Grid.Column="0" ,它是以0為索引開始布局的。我們需要注意的是

Grid.RowSpan="2" Grid.ColumnSpan="2"  屬性,它表示跨越2行,跨越2列的内容,顯示結果為:

布局

看見了吧,Grid是很有用處的。

以上就是主要的布局容器,可以作為頂層容器,也可以作為子容器,一般是不能被其他非容器包含的,但是有個東西除外,那就是Border,這個是邊框,可以為容器設定一個邊框,例如下面:

<code>&lt;</code><code>Border</code>  <code>BorderThickness</code><code>=</code><code>"10"</code> <code>BorderBrush</code><code>=</code><code>"Yellow"</code><code>&gt; 容器&lt;/</code><code>Border</code><code>&gt;</code>

運作結果如下:

布局

好了,就到這裡,比較簡單,但是如果能好好的利用這些布局容器以及元件,加上樣式Style調優的話,你會布局出非常酷的界面,當然我們要以項目為基礎,下面一節就開始我們的普通控件的簡要介紹了,由于篇幅有限,我們一般隻介紹普通用法,以及常用屬性,方法等,需要了解更多更具體内容,可以參考官方資料。

如果對布局的需求比較複雜,并且Canvas, StackPanel和Grid都不能滿足要求,可以嘗試建立一個自定義的面闆來實作子面闆裡的元素布局行為。具體的實作方法是繼承Panel類并且重寫其中的MeasureOverride和ArrangeOverride方法。