博客園客戶端UAP開發隨筆 -- 適配不同尺寸的屏幕


Windows 8誕生之初,Modern apps被設計在運行於全屏模式下。為了讓Windows在運行Modern app時繼續擁有前台多任務能力,Windows引入了一種全新的分屏技術“SnapView”。它允許將支持這種視圖的Modern app貼在屏幕一邊,以1/4 (實際上是邏輯分辨率寬度333左右)屏幕尺寸運行。這種視圖特別適於工具類應用(如詞典)和即時通訊類應用(如QQ)。分屏多任務也成了Windows 8區別於iPad和安卓Pad系統的重要特征。

當時程序員在考慮Modern App適配不同視圖和屏幕分辨率時,一般主要考慮Landscape View (FullScreenSize, Fill)、Portriat View和SnapView,以及一些常見的分辨率如1366*768、1920*1080等。

可能是Windows的開發者們覺得僅僅是SnapView還不夠,也可能是再次感悟到“Windows”的真諦,自Windows 10開始,Modern app允許以窗口形式運行。因此Modern app的窗口幾乎可以是任何尺寸,Windows Store App的顯示適配問題就需要再次拿出來聊聊了。

一般來說,Modern app尺寸變化的判斷和適配有以下4個時機:

· VisualStateManager

· DetermineVisualState

· Window.SizeChanged

· OnApplyTheme

1. VisualStateManger 是最常用的方法,也是最方便的方法。它的用法也相對簡單。先看一段XAML代碼:

<Page>
<Grid x:Name=”LayoutGrid”>
<VisualStateManager.VisualStateGroups>
            <!-- Visual states reflect the application's view state inside the FlipView -->
            <VisualStateGroup>
                <VisualState x:Name="FullScreenLandscape"/>
                <VisualState x:Name="Filled">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="AutoCompleteContainer" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="800"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SP_Main" Storyboard.TargetProperty="Orientation">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NavigationBarContainer" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SV_Main" Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource VerticalScrollViewerStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SP_Main" Storyboard.TargetProperty="Orientation">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="Vertical"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="searchBarControl" Storyboard.TargetProperty="Margin">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="10,0,10,0"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="searchBarControl" Storyboard.TargetProperty="Width">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="300"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
</Grid>
</Page>

VisualStateManager代碼位於Page的LayoutGrid下,以Storageboard的形式給出了不同視圖下需要做的適配性變化。以“SnapView”為例,我們通常給予SnapView更多關照,如container寬度的調整,ScrollView方向的調整,一些輔助的顯示控件的隱藏等等。值得欣慰的是,使用VisualStateManager的XAML代碼,你只需要考慮怎么來的,不需要考慮怎么回去。當VisualState發生變化時,StateManager會先讓視圖回到初始狀態,然后再執行新的變化。

必應詞典的SnapView就是用這種方式實現的:

image

2. DetermineVisualState

DetermineVisualState像是VisualStateManager的C#版本,它是一個重載函數,用於繼承了LayoutAwarePage的Page。來看一段代碼:

protected override string DetermineVisualState(ApplicationViewState viewState)
        {
            if (viewState == ApplicationViewState.Snapped)
            {
                if (_DefinitionControl != null)
                {
                    _DefinitionControl.SetToSnapStyle();
                }

                Grid_Layout.RowDefinitions[0].Height = new GridLength(60);
……
……
            }
            else
            {

             if (_DefinitionControl != null)
                {
                    _DefinitionControl.SetToLandscapeStyle();
                }

                Grid_Layout.RowDefinitions[0].Height = new GridLength(80);
                // semanticZoom.IsZoomOutButtonEnabled = true;

            }
…….
……
            return viewState.ToString();
        }

在DetermineVisualState中,可以手動添加一些代碼,做一些特殊處理,或者用VisualStateManager不容易表達的變化。但DetermineVisualState用起來就沒有VisualStateManager那么方便了,要知道怎么來的,還要知道怎么回去。這里的代碼應該盡可能的少一些。

3. Window.Current.SizeChanged

如果想更精細的控制窗口變化時的界面效果,可以抓住在Window. Current .SizeChanged這個時機:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
            Window.Current.SizeChanged += Current_SizeChanged;
}
Protected override void OnNavigatedFrom(NavigationeventArgs e)
{
        Window.Current.SizeChanged-=Current_SizeChanged;
}

void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
{
//do something here            
}

4. OnApplyTheme

在自定義控件顯示前,OnApplyTheme是一個比較常用的函數用來靈活的給頁面元素賦值、修改控件外觀。舉個”栗“子:

protected override void OnApplyTemplate()
 {
            Grid layoutGrid = GetTemplateChild("Grid_Layout") as Grid;
            if (_counter % 2 == 0)
                layoutGrid.Background = Application.Current.Resources["HomepageDataContainerBackground1"] as SolidColorBrush;
            else
                layoutGrid.Background = Application.Current.Resources["HomepageDataContainerBackground2"] as SolidColorBrush;

            StackPanel SP_KeyWords = GetTemplateChild("SP_KeyWords") as StackPanel;
            int counter = 1;
            foreach (KeyWord keyWord in _DailyNews.KeyWords)
            {
                KeyWordTile keyWordTile = new KeyWordTile(keyWord, counter);
                keyWordTile.KeyWordClicked += dailyNewsTile_KeyWordTileClicked;
                SP_KeyWords.Children.Add(keyWordTile);
                counter++;
            }
…. Do other things.
            base.OnApplyTemplate();
        }

掌握了以上四點,相信大家都能做出看起來很美、適配廣泛的的Modern App。

分享代碼,改變世界!

Windows Phone Store App link:

http://www.windowsphone.com/zh-cn/store/app/博客園-uap/500f08f0-5be8-4723-aff9-a397beee52fc

Windows Store App link:

http://apps.microsoft.com/windows/zh-cn/app/c76b99a0-9abd-4a4e-86f0-b29bfcc51059

GitHub open source link:

https://github.com/MS-UAP/cnblogs-UAP

MSDN Sample Code:

https://code.msdn.microsoft.com/CNBlogs-Client-Universal-477943ab

 


免責聲明!

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



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