Viewbox在UWP開發中的應用


Windows 8.1 與Windows Phone 8.1的UAP應用,終於在Windows 10上統一到了UWP之下。原來3個不同的project也變為一個。沒有了2套xaml頁面,我們需要用同一個頁面適應所有的設備。更麻煩的是在Desktop設備上,我們的應用窗口是可以隨意拖動大小的。這對我們的UI布局提出了更高的要求。當然我們也有了新的工具來應對:

VisualState中增加了StateTriggers,通過不同的條件觸發Trigger並自動切換到對應的VisualState,還能加入自己定義觸發條件的Trigger。

新增了RelativePanel控件,可以讓其中的元素使用相對位置布局來適應不同的設備和窗口大小。

另一方面微軟官方也發布了一些指導建議,比如Responsive design 101 for Universal Windows Platform (UWP) apps , UI basics for Universal Windows Platform (UWP) apps, Plan your Universal Windows Platform (UWP) app 等一系列文章。這對我們也很有啟發。

然而這些都沒有具體提到對於窗口大小拖動情況下的處理,下面就來分享一下我們在嘗試開發UWP應用的過程中對這種情況的一些思考。

總體布局

我們的應用,總體上是非常簡單地采用了UI basics for Universal Windows Platform (UWP) apps 中 圖1和圖2 的布局,有着始終顯示的頂欄和底欄,中間則是內容顯示區域。

如果沿用UAP的設計,我們可能會為頂欄和底欄設計一個固定高度,讓中間的內容區域可以隨屏幕大小來變化。然而在UWP中,我們的應用窗口可以在最小500 X 320,到全屏之間自由變化。如果仍然采用固定高度,那在窗口變小的情況下,內容區域就會被頂欄和底欄擠壓,這並不是我們希望的。所以我們在全局的布局上采用了按比例分配的策略:

<Grid.RowDefinitions>

<RowDefinition x:Name="rd_1" Height="*" ></RowDefinition>

<RowDefinition x:Name="rd_2" Height="8*"></RowDefinition>

<RowDefinition Height="60*"></RowDefinition>

<RowDefinition x:Name="rd_4" Height="8*" ></RowDefinition>

<RowDefinition x:Name="rd_5" Height="*" ></RowDefinition>

</Grid.RowDefinitions>

這樣一來在不同的窗口大小和設備的情況下都可以有所兼顧。

但這又帶來新的問題:我們頂欄和底欄中的文字,圖片大多是固定大小的。怎樣才能讓它們隨屏幕和設備自動適應呢?用新的StateTriggers固然可以,但對於每個固定大小的控件,都要指定它們在不同VisualState下的新大小,有些麻煩。而且我們的布局並沒有很大的變化,沒有一定使用StateTriggers必要。所以這里我們想到了Viewbox 控件。Viewbox 是一個可以將其中內容縮放到自身大小的容器。我們在按比例划分的Grid中放入Viewbox ,再把頂欄和底欄放到Viewbox 中,這樣他們就可以在不同窗口大小和設備上都保持統一的比例了:

<Viewbox x:Name="vbNav" Grid.Row="1" HorizontalAlignment="Left" Visibility="Visible">

<Grid Margin="50,0" >

<Image Source="{StaticResource mainPageMenuLeftImg}" Stretch="Uniform" HorizontalAlignment="Left" Height="160"

Margin="-20,0,0,0" VerticalAlignment="Center" Canvas.ZIndex="100"></Image>

<ListView x:Name="lvNav" SelectionMode="Single" Height="160" Canvas.ZIndex="99"

SelectionChanged="lvNav_SelectionChanged" HorizontalAlignment="Left"

VerticalAlignment="Center" ScrollViewer.HorizontalScrollMode="Enabled"

Background="#FFF6EBA1" ItemContainerStyle="{StaticResource ContextControlItemContainerStyle}">

<ListView.ItemsPanel>

<ItemsPanelTemplate>

<VirtualizingStackPanel Orientation="Horizontal" Margin="0" VerticalAlignment="Center"></VirtualizingStackPanel>

</ItemsPanelTemplate>

</ListView.ItemsPanel>

</ListView>

<Image Source="{StaticResource mainPageMenuRightImg}" Stretch="Uniform" HorizontalAlignment="Right" Height="160"

Margin="0,0,-20,0" VerticalAlignment="Center" Canvas.ZIndex="100"></Image>

</Grid>

</Viewbox>

這里的image和listview都是固定大小的,使用了viewbox以后就可以始終保持只占屏幕一定比例,而不會在小屏幕上超出Grid而在大屏幕上顯得比較小了。

內容布局

我們的頁面內容有2種,一種是內容列表,一種則是包括編輯和預覽的界面。

對於內容列表,我們使用了Responsive design 101 for Universal Windows Platform (UWP) apps中的resize策略。

主要是一個橫向滾動的GridView,在屏幕足夠高的情況下顯示3行或4行內容,較小的情況下則顯示2行。然而這個較小的情況實際上覆蓋了比較大的范圍,如果仍然使用固定大小的列表元素控件則會遇到和頂欄和底欄類似的問題。所以我們又一次使用了viewbox: 將內容區域放一個Grid在最外層,再把包含GridView的viewbox放在其中。響應最外層的Grid的sizechange事件,改變GridView的長寬比例以適應顯示區域。

Xaml:

<Grid x:Name="grid_content" SizeChanged="gridRoot_SizeChanged" Grid.Row="2">

<Viewbox>

<GridView x:Name="gv_Content" ItemContainerStyle="{StaticResource contentTemplateStyle}"

SelectionMode="Single" IsSynchronizedWithCurrentItem="{x:Null}"

SelectionChanged="gvContent_SelectionChanged" IsItemClickEnabled="True"

VerticalAlignment="Stretch" HorizontalAlignment="Stretch"

Width="630"

Height="774"

ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.HorizontalScrollBarVisibility="Visible"

Margin="20">

<GridView.ItemsPanel>

<ItemsPanelTemplate>

<WrapGrid Orientation="Vertical" Margin="0" MaximumRowsOrColumns="4" VerticalAlignment="Top"></WrapGrid>

</ItemsPanelTemplate>

</GridView.ItemsPanel>

</GridView>

</Viewbox>

</Grid>

CS:

private void gridRoot_SizeChanged(object sender, SizeChangedEventArgs e)

{

try

{

Grid thisGrid = sender as Grid;

if (thisGrid.ActualHeight >=480 && thisGrid.ActualHeight <=720)

{

this.gv_Content.Height = 784 * 1.5; //改變高度,放3個列表元素

}

else if (thisGrid.ActualHeight >720)

{

this.gv_Content.Height = 784 * 2; //改變高度,放4個列表元素

}

     else

{

this. gv_Content.Height = 784; //改變高度,放2個列表元素

}

this. gv_Content.Width = thisGrid.ActualWidth / (thisGrid.ActualHeight) * this. gv_Content.Height; //調整寬度,適應顯示區域比例

}

catch (Exception ex)

{

Debug.WriteLine(ex.Source + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);

}

}

而包含編輯和預覽的界面,我們則采取了在屏幕寬度較小的時候將預覽界面隱藏,讓界面可以在編輯和預覽之間切換的策略。

小結

以上就是我們面對UWP在UI布局方面新特性的一部分心得,希望能拋磚引玉,吸引更多的小伙伴加入到UWP的開發中來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM