FullScreenLandscape:全螢幕
FullScreenPortrait:寬度為 500px ~ 螢幕的一半以下
Filled:寬度大於螢幕的一半 ~ 螢幕寬度 - 500px
大致上如果想在這三種不同的尺寸下指定不同的排版樣式,搭配 MVVM 是最節省作業系統資源及開發成本的方式,在 Windows RT 時期常會使用 LayoutAwarePage 來簡單達到效果,在 Store App 時方式差不多,但需要經過小部分改寫才能使用,搜尋了一下實在找不到官方對於 LayoutAwarePage 的介紹,可能暫時得開 Windows RT 的 Template 來參考,另外官方建議在將專案轉至 8.1 時將 LayoutAwarePage 移除的方式在這:API changes for Windows 8.1(XAML)
以下我將 LayoutAwarePage 對於 WindowsSizeChange 時切換 View 的方式集中起來讓 Windows Store App 也可以根據視窗尺寸改變排版方式,這裡注意我使用了 #if WINDOWS_APP 的方式將類別內容全部包起來了,因為我將這個類別放在 Universal Apps 的 Shared Project 內,而這個類別內有太多 Windows Phone SDK 不支援的 API。
public class WindowsLayoutSupportPage : Page
{
#if WINDOWS_APP
private List<Control> _layoutAwareControls;
public WindowsLayoutSupportPage()
{
if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
Loaded += OnWindowsLayoutSupportPageLoaded;
Unloaded += OnWindowsLayoutSupportPageUnloaded;
}
}
void OnWindowsLayoutSupportPageLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
StartLayoutUpdates(sender, e);
}
protected void OnWindowsLayoutSupportPageUnloaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
StopLayoutUpdates(sender, e);
}
public void StartLayoutUpdates(object sender, RoutedEventArgs e)
{
var control = sender as Control;
if (control == null) return;
if (this._layoutAwareControls == null)
{
SizeChanged += this.OnPageSizeChanged;
this._layoutAwareControls = new List<Control>();
}
this._layoutAwareControls.Add(control);
VisualStateManager.GoToState(control, DetermineVisualState(ApplicationView.Value), false);
}
public void StopLayoutUpdates(object sender, RoutedEventArgs e)
{
var control = sender as Control;
if (control == null || this._layoutAwareControls == null) return;
this._layoutAwareControls.Remove(control);
if (this._layoutAwareControls.Count == 0)
{
this._layoutAwareControls = null;
SizeChanged -= this.OnPageSizeChanged;
}
}
protected string DetermineVisualState(ApplicationViewState viewState)
{
return viewState.ToString();
}
public void InvalidateVisualState()
{
if (this._layoutAwareControls != null)
{
string visualState = DetermineVisualState(ApplicationView.Value);
foreach (var layoutAwareControl in this._layoutAwareControls)
{
VisualStateManager.GoToState(layoutAwareControl, visualState, false);
}
}
}
private void OnPageSizeChanged(object sender, SizeChangedEventArgs e)
{
InvalidateVisualState();
}
#endif
}
有了上面這個類別後,我們將需要支援改變 View 的 Page 改為這個類別,即可在最上方所列出來的三種尺寸切換不同的容器,配合同樣的 DataContext 其實增加的負擔不會太大,以下這個例子我讓 MainPage 可以在 FullL、FullP、Fill 三種尺寸下各選擇不同的容器,僅需針對 XAML 做修改即可在改變尺寸時讓視窗內容在藍、綠、紅三個 Grid 做切換
<local:WindowsLayoutSupportPage
x:Class="UAPractice.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UAPractice"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid x:Name="FullLandscapeView"
Background="#00AED8"
AutomationProperties.AutomationId="FullLandscapeView">
</Grid>
<Grid x:Name="FullPortraitView"
Background="#99FF99"
AutomationProperties.AutomationId="FullPortraitView"
Visibility="Collapsed">
</Grid>
<Grid x:Name="FillView"
Background="#FF9999"
AutomationProperties.AutomationId="FillView"
Visibility="Collapsed">
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FillView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FullLandscapeView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FullPortraitView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FullLandscapeView" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</local:WindowsLayoutSupportPage>
沒有留言:
張貼留言