天天看點

Windows 8.1 應用再出發 - 視圖狀态的更新

本篇我們來了解一下Windows 8.1 給應用的視圖狀态帶來了哪些變化,以及我們怎麼利用這些變化作出更好的界面視圖。

首先我們來簡單回顧一下Windows 8.0 時代的視圖狀态:

Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新

上圖中,從左到右依次是Windows 8 應用的三種視圖狀态:Full Screen, Snapped 和 Filled。

其中Snapped 和 Filled 狀态隻能顯示在橫向分辨率在1366像素或更高的螢幕中。而Snapped視圖固定寬度為320像素。

我們對視圖狀态的判斷和使用主要會用到ApplicationView.Value 來擷取目前視圖狀态的值,它是枚舉類型,包括FullScreenLandscape,Filled,Snapped 和 FullScreenPortrait 四種。

我們在頁面的SizeChanged 事件中判斷目前視圖狀态值來對頁面做出調整。Windows 8 中的視圖狀态就說到這裡,為什麼隻是簡單描述,連示例代碼都沒有呢?

因為Windows 8.1 中視圖狀态的處理發生了很大的變化,ApplicationView.Value 也不再适用。

下面我們來看看視圖狀态在 Windows 8.1 中的變化:

1)不再有Filled 和 Snapped 兩種視圖狀态,這是因為8.1 中應用不再以320像素的貼靠狀态出現。使用者可以拖動應用的寬度直至大小最小寬度(最小寬度在應用清單檔案中設定,有500和320像素可選)。

Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新
2)應用分為全屏狀态和非全屏狀态,在非全屏狀态時,因為螢幕上可以同時容納多于兩個應用橫向排列,是以應用狀态分為貼近螢幕左側,貼近螢幕右側 和 都不貼近的狀态。
Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新

3)當在應用中啟動其他應用,例如點選連結啟動IE 時。預設兩個應用會橫向平分螢幕空間,但是我們可以設定讓應用比啟動的應用更寬,更窄,變為最小寬度,或者變得不可見。而這個設定是通過LauncherOptions 的 DesiredRemainingView 來完成的。

造成這些變化的很重要的一個類就是ApplicationView,我們來看看這個類的變化:

如我們前面所說,ApplicationView.Value  不再适用,取而代之的,添加了幾個新的屬性:Orientation,IsFullScreen,AdjacentToLeftDisplayEdge 和 AdjacentToRightDisplayEdge。

我們可以用Orientation 屬性來判斷螢幕目前方向,使用IsFullScreen來判斷應用是否為全屏狀态,然後使用AdjacentToLeftDisplayEdge 和 AdjacentToRightDisplayEdge 來判斷應用目前的位置。

因為固定貼靠狀态被取消,是以Application.TryUnsnap 方法也不再适用。同時添加了兩個新方法:GetForCurrentView 和 GetApplicationViewIdForWindow。

來看看ApplicationView 類的使用方法:

//頁面的尺寸變化事件
private void pageRoot_SizeChanged(object sender, SizeChangedEventArgs e)
{
    // 擷取目前應用視圖
    ApplicationView view = ApplicationView.GetForCurrentView();
    if (view.IsFullScreen)
    {
        // 應用處在全屏狀态
    }
    else if (view.AdjacentToLeftDisplayEdge)
    {
        // 應用貼近螢幕左側
    }
    else if (view.AdjacentToRightDisplayEdge)
    {
        // 應用貼近螢幕右側
    }
    else
    {
        // 應用在兩個應用中間
    }
}      

上面代碼中示範了ApplicationView 中很多屬性的意義和判斷方法,下面我們來說一下視圖狀态變化時應該注意的地方:

1)考慮應用視圖大小對控件布局的影響。例如應用菜單欄的布局,彈出框的尺寸和位置等。

2) 如果最小寬度為320,那麼應用内布局的調整可以分為兩個階段。從螢幕寬度的一半到500像素寬為第一階段,這一階段還不需要對布局做特殊的調整,可以讓應用内部橫向滾動顯示,當然你可以對應用中的圖檔等元素做尺寸的縮放。從500 到 320 像素寬的時候,由于視圖較窄,我們需要将應用布局改為垂直布局視圖,并縮小标題和回退按鈕尺寸,同時布局與邊距的距離也要調整。

我們來看一個例子:

XAML 代碼 :

<Page x:Name="pageRoot" x:Class="Win8._1UpdateControls.UpdateControls.AppViewPage" 
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    SizeChanged="pageRoot_SizeChanged" RequestedTheme="Light" mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <!-- Back button and page title -->
        <Grid x:Name="defaultNavigation" Visibility="Visible">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                        Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top"
                        AutomationProperties.Name="Back" AutomationProperties.AutomationId="BackButton" AutomationProperties.ItemType="Navigation Button"/>
            <TextBlock x:Name="pageTitle" Text="Default ApplicationView" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                        IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
        </Grid>
        <!-- Minimal Back button and page title -->
        <Grid x:Name="minimalNavigation" Visibility="Collapsed">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="80"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <AppBarButton x:Name="backButtonMinimal" Margin="19,59,19,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
                        Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top"
                        AutomationProperties.Name="Back" AutomationProperties.AutomationId="BackButton" AutomationProperties.ItemType="Navigation Button">
                <AppBarButton.RenderTransform>
                    <CompositeTransform ScaleX="0.75" ScaleY="0.75"/>
                </AppBarButton.RenderTransform>
            </AppBarButton>
            <TextBlock x:Name="pageTitleMinimal" Text="Minimal ApplicationView" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" FontSize="27"
                       IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,60"/>
        </Grid>
        
        <StackPanel Grid.Row="1" Orientation="Horizontal" x:Name="panel">
            <Border Width="300" Height="300" Background="DarkOrange"/>
            <Border Width="300" Height="300" Grid.Column="1" Background="DarkGray"/>
            <Border Width="300" Height="300" Grid.Column="2" Background="DarkCyan"/>
        </StackPanel>

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="DefaultLayout">
                    <!-- The default properties are set in the XAML. -->
                </VisualState>
                <VisualState x:Name="MinimalLayout">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="defaultNavigation" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="minimalNavigation" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="panel" Storyboard.TargetProperty="Orientation">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
                    </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</Page>      

C# 中的處理代碼:

private void pageRoot_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            ApplicationView view = ApplicationView.GetForCurrentView();

            if (!view.IsFullScreen && e.NewSize.Width < 500)
            {
                VisualStateManager.GoToState(this, "MinimalLayout", true);
            }
            else
            {
                VisualStateManager.GoToState(this, "DefaultLayout", true);
            }
        }      

例子中,我們在VisualStateManager中定義了兩種視圖:DefaultLayout 和 MinimalLayout 。DefaultLayout 維持XAML原狀,而MinimalLayout 的變化是減小了标題和回退按鈕的尺寸和間隔,将StackPanel由橫向排列改為縱向排列。對VisualStateManager 中視圖狀态切換的調用發生在 pageRoot_SizeChanged 方法中。當頁面寬度小于500時,切換到MinimalLayout 狀态,否則恢複DefaultLayout 狀态。

來看看運作效果:

Windows 8.1 應用再出發 - 視圖狀态的更新
Windows 8.1 應用再出發 - 視圖狀态的更新

我們看到,當應用視圖寬度小于500時,我們通過視圖狀态的變化完成了我們想要的頁面效果。例子本身很簡單,更多的是說明思路讓大家有一個直覺的認識。

這樣我們就把視圖狀态在Windows 8.1 中的變化介紹完了,希望對大家有所幫助,謝謝。

繼續閱讀