Windows10 UWP開發 - 響應式設計

原文: Windows10 UWP開發 - 響應式設計

 

Windows10 UWP開發 - 響應式設計

本篇隨筆與你們簡單討論一下在開發適配不一樣分辨率、寬高比的Windows10 Universal App佈局時的可行方式與小技巧。經驗均從實踐中總結,可能有諸多不完善和淺薄之處,歡迎讀者嚴格指正。另外本文也只是拋磚引玉之用,但願能收穫更多更好的實戰經驗。css

自適配的必要性

說了這麼多,咱們首先可能會問了,爲何要作響應式設計?其緣由有如下兩點:html

Windows10的跨平臺性

Windows10是微軟宣稱能夠統一運行於PC&平板&手機&Xbox等諸多平臺的操做系統,固然這也是universal一詞的由來。若是你但願你的應用不只僅侷限於某一個平臺,那麼作一些響應式佈局就很是必要了。前端

Win10 UWP的容器窗口可自定義大小

即便你的應用僅針對windows rt的平板用戶,win10對於uwp的全新處理方式也讓開發者不能免於分辨率適配。下圖分別是Win8.1和Win10的應用商店應用對比:
  
不難發現,爲了加強store app的實用度,桌面環境下的uwp是能夠自定義窗口尺寸的。爲了讓應用別輕易被用戶玩崩壞,整理整理儀容仍是至關有必要的。canvas

廢話少說,接下來,咱們來看看手中能用於作響應式設計的手段吧。windows

自適配佈局的方法

與網頁設計類比

不知道讀者們有多少有html+css佈局經歷,這一套東西儘管在佈局上不算完美,但用起來也算駕輕就熟,熟悉後能使網頁佈局有基本良好的適應性。
因此這裏我就先說說網頁前端佈局與XAML佈局的區別與聯繫吧。好消息是,一言以蔽之:幾乎HTML能作的、XAML均可以。具體地說,幾種在網頁佈局上常見手法xaml實現以下:app

順序佈局

也就是沒有佈局咯…對於結構簡單的內容呈現(好比本篇博客),用這種方式足矣。如同下面的代碼模型同樣 框架

<!DOCTYPE html>
<html>
    <body>
        <p style="font-size:70px">I am title</p>
        <div style="width:100px;height:100px;background:rgb(230,230,250);display:inline-block;"></div>
        <span style="font-size:30px">Inline text</span>
        <div style="font-size:32px">
            The quick brown fox jumps over the lazy dog.
            The quick brown fox jumps over the lazy dog.
            The quick brown fox jumps over the lazy dog.
            The quick brown fox jumps over the lazy dog.
            The quick brown fox jumps over the lazy dog.
        </div>
    </body>
</html>

全部的元素從上到下、左到右排列,排列不下的則進入下一行。該效果使用HTML實現很是簡單,因爲大部分html元素是inline的,故直接將其從上到下排列便可。工具

在XAML中,事情會麻煩一點,因爲全部元素均不佔位而浮動於界面上,故須要藉助其餘控件的幫助:Grid可用來從上到下安排元素,而對於同一行的元素則能夠用stackpanel安排。若是須要響應度更高的佈局如當寬度不夠時自動換行等特性,則需配合ListView與ItemsWrapGrid進行佈局。詳細代碼模型見下,十分簡單,故再也不贅述。 佈局

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel Orientation="Vertical" Margin="70,70,70,10">
        <TextBlock Text="I am title."  FontSize="70"/>
        <StackPanel Orientation="Horizontal">
            <Grid Background="Lavender" Width="100" Height="100"/>
            <TextBlock Text="Inline text." VerticalAlignment="Bottom" FontSize="30"/>
        </StackPanel>
        <TextBlock Text="The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog." TextWrapping="Wrap" FontSize="32"/>
    </StackPanel>
</Grid>

Absolute大法

有一種說法叫以不變應萬變。
無論在什麼狀況下,這種佈局方式是通配而廣泛的:設計時固定頁面尺寸,按照固定位置對每個元素進行佈局,若是框架太小則使用滾動條瀏覽,框架過大則自動居中。反映在html中,則是無處不在的position:absolute。
這樣的優勢在於方便設計,能最大程度(或者說,絲絕不差)復現designer的設計,且節省工做量(如對於電腦設計一個1366x768的佈局後通用所有窗口大小)。缺點則很明顯:缺少靈活性,用戶不友好,故只對於特定業務適用。 post

<div style="width:500px;height:500px;background:rgb(230,230,250);position:relative;">
    <div style="width:130px;height:130px;background:#332CC7;position:absolute;left:20px;top:20px;">
    </div>
    <div style="width:310px;height:310px;background:#4CA5FF;position:absolute;left:170px;top:170px;">
    </div>
    <div style="width:310px;position:absolute;left:170px;top:75px;font-size:28px;">
        The quick brown fox jumps over the lazy dog.
    </div>
    <div style="width:150px;position:absolute;left:20px;top:170px;font-size:28px;">
        The quick brown fox jumps over the lazy dog.
    </div>
</div>

UWP利用Canvas控件實現絕對佈局,其內部元素均利用Canvas.left/Canvas.top與頂部對齊。 

<Canvas Background="Lavender" Margin="70,70,70,70" Width="500" Height="500">
      <Grid Background="#FF332CC7" Width="130" Height="130" Canvas.Left="20" Canvas.Top="20">
      </Grid>
      <TextBlock 
          Canvas.Top="75" Canvas.Left="170" Width="310"
          Text="The quick brown fox jumps over the lazy dog. " 
          TextWrapping="Wrap" FontSize="28"/>
      <Grid Background="#FF4CA5FF" Width="310" Height="310" Canvas.Left="170" Canvas.Top="170">
      </Grid>
      <TextBlock 
          Canvas.Top="170" Canvas.Left="20" Width="150"
          Text="The quick brown fox jumps over the lazy dog. " 
          TextWrapping="Wrap" FontSize="28"/>
</Canvas>

流式佈局

流式佈局是網頁設計中挺老的概念了,將佈局分解成區塊,區塊大小與區塊間距均按頁面整體尺寸百分比變化,從而適應不一樣分辨率的窗口。而對於區塊內部細節,則可根據內容和需求進行定製。
該佈局方式在xaml中實現十分簡單,也並不是windows10的新東西,只須要在Grid的寬高定義時用*標明百分比便可。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="5*"/>
        <ColumnDefinition Width="90*"/>
        <ColumnDefinition Width="5*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="5*"/>
        <RowDefinition Height="90*"/>
        <RowDefinition Height="5*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Column="1" Grid.Row="1" Background="Lavender">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="35*"/>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="64*"/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="1" Background="White">
        </Grid>
        <Grid Grid.Column="2">
            <Grid.RowDefinitions>
                <RowDefinition Height="50*"/>
                <RowDefinition Height="10"/>
                <RowDefinition Height="50*"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="1" Background="White">
            </Grid>
        </Grid>
    </Grid>
</Grid>

實現效果以下:

XAML獨具特點的新方式

XAML自身一些具備特點的屬性/控件能進一步幫忙簡化響應式佈局,力求作到不用代碼。

Viewbox

Viewbox是一個控件,會將其容納的對象渲染成指定的寬高,在佈局很難作出改變且須要適應的變化並不大時可使用該方法。
關於其具體使用的tips&tricks咱們會另起一篇日誌介紹。

Rendertransform

爲UIElement的一個屬性,會將對象在渲染層面按某種規則進行變化,如拉伸/翻轉等。須要注意的是,所謂渲染層面,表如今與該控件有關的屬性是不會察覺的:如width/height屬性,將並不會知曉做用於其上的拉神操做。
以下面這段代碼將伸縮Grid的寬高:

<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Grid Height="500" Width="450" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Grid.RenderTransform>
            <ScaleTransform x:Name="scaler"
                    CenterX="0.5" CenterY="0"
                    ScaleX="1.3"
                    ScaleY="1.3" 
            />
        </Grid.RenderTransform>
    </Grid>
</Canvas>

配合着canvas.left/top屬性以及一些代碼,將至關容易地自制一個viewbox。

RelativePanel+VisualStateManager

兩者均爲Windows10引入的新特性,前者用於容許其子元素按相對位置(附着下方、附着於上方、左右對齊等方式進行排版且在佈局有變時自動調整保證其知足給定的位置關係);後者則定義多組VisualState,每個state對應頁面上不一樣控件的一些屬性值,而在對應的state條件知足時自動將屬性切換至目標值。此兩點結合,將能夠在不少狀況下不用額外的C#代碼實現響應佈局。

關於此工具的具體用法,在以前發佈的針對Build2015文章UWP?UWP! - Build 2015有些啥?(2)中已經說起,此處再也不贅述。

Code動態調整

上面的方法都很差使?那就用code吧,麻煩是麻煩一點,其使用起來是最自由和可定製的,只要開發者心中有佈局目標,就能知足一切排版需求。可是在用Code調整佈局的過程當中,仍是有一些注意事項值得嘮叨嘮叨的:

事件驅動動態調整

顯然,調整佈局的code是事件驅動而不是一直運行的,那麼寫在什麼事件裏呢?首先你們應該能想到SizeChanged。是的,SizeChanged事件發生於對應目標的尺寸發生變化以後,也就是說,在該事件被觸發時,保證能獲取正確的寬高、從而根據獲取到的數據進行動態佈局,故將代碼寫進該事件是徹底正確的選擇。須要注意的是,位置的變化(如canvas.left值改變)不會觸發該事件。另外須要注意的一點是,在事件中寫入的代碼不能直接/間接修改自身相關的尺寸,不然引起雪崩效應,可能帶來stackoverflow。  

LayoutUpdated也能夠用於尺寸變化檢測,可是它是一個更廣泛的事件:在佈局樹上的元素髮生改變就會觸發該事件,且該事件並不指定觸發對象,若是跟蹤該事件將發現不管窗口發生怎麼樣的改變,都將觸發海量的LayoutUpdated事件。故將代碼寫於其中並不明智。

ActualSize的獲取時機

在根據尺寸動態佈局的的代碼中少不了獲取ActualSize,但須要明確的是在佈局剛作出改變時ActualSize是不會生效的,直接以該值做爲基準勢必致使錯誤。解決方案有2:1.如上文所言,將事件寫於SizeChanged中,或將部分代碼依賴該事件觸發;2.強制調用UpdateLayout()方法,同步更新界面,從而能保證在該調用後得到的實際尺寸爲真實尺寸。

總結

佈局方法千千萬萬,本文只從最小的幾個地方入手簡要介紹,若需作出真正用戶友好、貼近業務需求的響應式佈局,還需綜合應用各類佈局手段,瞭解各手段間優劣以及其最適合的應用場景,協同做用以創造好的佈局。

相關文章
相關標籤/搜索