天天看點

第五章:尺寸處理(1)

您已經看到了與各種視覺元素相關的尺寸參考:

然後是Device.GetNamedSize,它為NamedSize枚舉的各種成員傳回一個适用于Label或Button的FontSize值的平台相關編号。

這些數字是什麼?他們的機關是什麼?我們如何智能地将需要大小的屬性設定為其他值?

好問題。如您所見,各種平台具有不同的螢幕尺寸和不同的文本大小,并且都在螢幕上顯示不同數量的文本。這是Xamarin.Forms應用程式可以預見或控制的文本數量嗎?即使有可能,這是一個合适的程式設計習慣嗎?應用程式是否應調整字型大小以在螢幕上獲得所需的文本密度?

通常,在編寫Xamarin.Forms應用程式時,最好不要太靠近可視對象的實際數字次元。最好相信Xamarin.Forms和各個平台來做出最好的預設選擇。

但是,有時候程式員需要知道特定視覺對象的大小以及它們出現的螢幕大小。

像素,點,dps, DIPs和DIUs

視訊顯示由矩形的像素陣列組成。 螢幕上顯示的任何對象也具有像素大小。 在個人電腦的早期,程式員以像素為機關調整和定位視覺對象。 但随着螢幕尺寸和像素密度越來越多,使用像素對于嘗試編寫在許多裝置上大緻相同的應用程式的程式員而言變得不可取。 需要另一個解決方案。

這些解決方案始于桌面計算機的作業系統,然後适用于移動裝置。 出于這個原因,用桌面開始這種探索是很有啟發性的。

桌面視訊顯示器具有廣泛的像素尺寸,從近乎過時的640×480到成千上萬。 4:3的寬高比曾經是電腦顯示器的标準配置,也是電影和電視的标準配置,但16:9(或類似16:10)的高清寬高比現在更為普遍。

桌面視訊顯示器的實體尺寸通常以英寸或厘米為機關,沿螢幕對角線測量。像素尺寸與實體尺寸的組合允許您以每英寸點數(DPI)計算視訊顯示器的分辨率或像素密度,有時也稱為每英寸像素數(PPI)。顯示分辨率也可以測量為點距,這是相鄰像素中心之間的距離,通常以毫米為機關進行測量。

例如,您可以使用畢達哥拉斯定理來計算古老的800×600顯示器的對角線長度為1,000,800平方的平方根加600平方。如果此顯示器的對角線為13英寸,則像素密度為77 DPI,或點距為0.33毫米。但是,現代筆記本電腦上的13英寸螢幕可能具有2560×1600的像素尺寸,其像素密度約為230 DPI,或者點間距約為0.11毫米。此螢幕上的100像素正方形對象的大小與舊螢幕上同一對象的大小相同。

程式員在嘗試正确确定視覺元素的大小時應該有戰鬥機會。出于這個原因,蘋果和微軟都設計了桌面計算系統,允許程式員以某種形式的獨立于裝置的單元而不是像素來處理視訊顯示。程式員遇到和指定的大部分次元都在這些與裝置無關的單元中。作業系統有責任在這些單元和像素之間來回轉換。

在Apple世界中,桌面視訊顯示器傳統上被認為具有72英寸的分辨率。這個數字來自印刷術,許多測量都是以點為機關。在古典印刷術中,英寸約有72點,但在數字印刷術中,該點已标準化為一英寸的七十二分之一。通過使用點而不是像素,程式員可以直覺地了解數字大小與可視對象在螢幕上占據的區域之間的關系。

在Windows世界中,開發了一種類似的技術,稱為裝置無關像素(DIP)或裝置無關單元(DIU)。對于Windows程式員來說,桌面視訊顯示器的分辨率假定為96個DIU,雖然可以由使用者進行調整,但其分辨率仍然高于72 DPI的三分之一。

然而,移動裝置的規則有所不同:現代手機所達到的像素密度通常比桌面顯示器高得多。這種更高的像素密度允許文本和其他視覺對象在變得難以辨認之前縮小得多。

與桌上型電腦或筆記本電腦螢幕相比,電話通常也更貼近使用者的臉部。這種差異還意味着手機上的可視對象可能比桌面或筆記本電腦螢幕上的可比對象更小。由于手機的外形尺寸比桌面顯示器小得多,是以縮小視覺對象是非常理想的,因為它允許更多地适合螢幕。

Apple繼續将iPhone上的裝置無關單元稱為點。直到最近,蘋果所有的高密度顯示器(Apple稱之為Retina)都有兩個像素點的轉換。對于MacBook Pro,iPad和iPhone來說也是如此。最近的例外是iPhone 6 Plus,它有三個像素點。

例如,iPhone 4的3.5英寸螢幕的640×960像素尺寸具有約320DPI的實際像素密度。有兩個像素點,是以對于在iPhone 4上運作的應用程式,螢幕顯示尺寸為320×480點。 iPhone 3實際上的像素尺寸為320×480,點數等于像素,是以對于在這兩個裝置上運作的程式,iPhone 3和iPhone 4的顯示器看起來大小相同。盡管尺寸相同,但圖形對象和文本在iPhone 4上的顯示分辨率要高于

iPhone 3。

對于iPhone 3和iPhone 4,螢幕尺寸和點尺寸之間的關系意味着轉換因子為英寸160點,而不是桌面标準72。

iPhone 5擁有4英寸螢幕,但像素尺寸為640×1136.像素密度與iPhone 4大緻相同。對于程式,此螢幕的尺寸為320×768點。

iPhone 6擁有4.7英寸的螢幕和750×1334的像素尺寸。像素密度也約為320 DPI。有兩個像素的點,是以對于一個程式,螢幕似乎有一個375×667的點大小。

但是,iPhone 6 Plus具有5.5英寸的螢幕,像素尺寸為1080×1920,其像素密度為400 DPI。這個更高的像素密度意味着更多的像素點,對于iPhone 6 Plus,Apple已經設定了等于三個像素的點。這通常意味着螢幕尺寸為360×640點,但對于程式而言,iPhone 6 Plus螢幕的點大小為414×736,是以感覺分辨率約為150英寸。

下表總結了這些資訊:

第五章:尺寸處理(1)

Android做了一些非常類似的事情:Android裝置具有各種尺寸和像素尺寸,但Android程式員通常以密度無關像素(dps)為機關工作。像素和Dps之間的關系假定為160英寸英寸,這意味着Apple和Android裝置無關機關非常相似。

微軟采取了與Windows Phone 7不同的方法。原始的Windows Phone 7裝置具有480×800像素的螢幕尺寸,其通常被稱為WVGA(寬視訊圖形陣列)。應用程式以像素為機關處理此顯示。如果您假設480×800 Windows Phone 7裝置的平均螢幕尺寸為4英寸,這意味着Windows Phone 7隐含地假定像素密度約為240 DPI。這是iPhone和Android裝置的假設像素密度的1.5倍。最終,允許使用幾種較大的螢幕尺寸:768×1280(WXGA或寬幅擴充圖形陣列),720×1280(以高清電視術語表示為720p)和1080×1920(稱為1080p)。對于這些額外的顯示尺寸,程式員在獨立于裝置的單元中工作。在像素和裝置無關單元之間轉換的内部比例因子,是以縱向模式下螢幕的寬度始終顯示為480像素。

使用Windows Phone 8.1中的Windows Runtime API,基于螢幕的像素大小和螢幕的實體大小引入了不同的縮放因子。下面的表格基于Windows Phone 8.1仿真器使用一個名為WhatSize的程式放在一起,您将很快看到:

第五章:尺寸處理(1)

縮放因子是根據寬度計算的,因為WhatSize程式顯示的DIU中的高度不包括Windows Phone狀态欄。 最終的DPI數字是根據全像素大小,螢幕對角線大小(英寸)和比例因子計算得出的。

除WVGA異常值外,計算出的DPI已經足夠接近與iOS和Android裝置相關的160 DPI标準。

Windows 10 Mobile使用稍高的縮放因子,并且以0.25的倍數而不是0.2。 下表根據Windows 10 Mobile仿真器放在一起:

第五章:尺寸處理(1)

您可能會得出這樣的結論:Windows 10 Mobile的平均DPI平均值為144(四舍五入到最接近的16的倍數)而不是160.或者您可以說它足夠接近160以便認為它與iOS和Windows Phone一緻。

Xamarin.Forms具有盡可能多地使用底層平台約定的理念。 按照這個理念,Xamarin.Forms程式員可以處理每個特定平台定義的大小。 程式員通過Xamarin.Forms API遇到的所有尺寸都在這些平台特定的,獨立于裝置的單元中。

Xamarin.Forms程式員通常可以以獨立于裝置的方式處理手機顯示屏,并具有以下分辨率:

VisualElement類定義了兩個名為Width和Height的屬性,它們提供了這些裝置無關單元中視圖,布局和頁面的渲染尺寸。但是,寬度和高度的初始設定是“模拟”值-1。這些屬性的值隻有在布局系統在頁面上定位和調整所有内容時才有效。另外,請記住,HorizontalOptions或VerticalOptions的預設填充設定通常會導緻視圖占用更多的空間。寬度和高度值反映了這個額外的空間。 “寬度”和“高度”值還包括可以在元素上設定的任何填充,并且與視圖的BackgroundColor屬性着色的區域一緻。

VisualElement定義了一個名為SizeChanged的事件,每當Width或

視覺元素的高度屬性發生變化。此事件是頁面布局時發生的幾個通知的一部分,這是一個涉及頁面各種元素大小和位置的過程。此布局過程發生在頁面的第一個定義(通常在頁面構造函數中)之後,并且響應于可能影響布局的任何更改而發生新的布局傳遞 - 例如,視圖添加到ContentPage或StackLayout時,從這些對象中移除,或者在視覺元素上設定可能導緻其尺寸變化的屬性。

當螢幕尺寸改變時,新的布局也會觸發。這主要發生在手機在縱向和橫向模式之間旋轉時。

對Xamarin.Forms布局系統的完全熟悉通常伴随着編寫自己的Layout 派生物的工作。此任務在第26章“自定義布局”中等待我們。在此之前,隻需知道“寬度”和“高度”屬性的更改對于處理可視對象的大小有幫助。您可以将一個SizeChanged處理程式附加到頁面上的任何可視對象,包括頁面本身。 WhatSize程式示範如何擷取頁面大小并顯示它:

點選(此處)折疊或打開

這是本書中事件處理的第一個例子,您可以看到事件是以正常的C#和.NET方式處理的。構造函數末尾的代碼将OnPageSizeChanged事件處理程式附加到頁面的SizeChanged事件。事件處理程式(通常命名為sender)的第一個參數是引發事件的對象,在這種情況下是WhatSizePage的執行個體,但事件處理程式不使用它。事件處理程式也不使用第二個參數 - 所謂的事件參數 - 有時會提供有關該事件的更多資訊。

相反,事件處理程式通路Label元素(友善地儲存為字段)以顯示頁面的Width和Height屬性。 String.Format調用中的Unicode字元是一個times(×)符号。

SizeChanged事件不是獲得元素大小的唯一機會。 VisualElement還定義了一個名為OnSizeAllocated的受保護虛拟方法,用于訓示何時為可視元素配置設定了大小。您可以在ContentPage派生中重寫此方法,而不是處理SizeChanged事件,但有時在大小實際未更改時調用OnSizeAllocated。

這是在三個标準平台上運作的程式:

第五章:尺寸處理(1)

為了記錄,這些是這三個圖像中螢幕的來源:

請注意,Android上程式感覺的垂直尺寸不包括狀态欄或底部按鈕占用的區域; Windows 10 Mobile裝置的垂直尺寸不包括狀态欄占用的區域。

預設情況下,所有三個平台都會響應裝置方向更改。 如果逆時針旋轉手機(或仿真器)90度,手機将顯示以下尺寸:

第五章:尺寸處理(1)

本書的螢幕截圖僅為肖像模式而設計,是以您需要橫向翻閱本書,以了解該程式在橫向上的效果。 Android上的598像素寬度排除了按鈕的區域; 335像素的高度不包括狀态欄,該狀态欄始終顯示在頁面上方。 在Windows 10 Mobile裝置上,728像素寬度不包括狀态欄的區域,該區域顯示在相同的位置,但帶有旋轉的圖示以反映新的方向。

這是iPad Air 2模拟器上運作的程式,像素尺寸為2048×1536。

第五章:尺寸處理(1)

顯然,縮放因子是2.螢幕對角線為9.7英寸,分辨率為132 DPI。

Surface Pro 3的像素尺寸為2160×1440.縮放系數可由使用者選擇以使螢幕上的所有内容變大或變小,但推薦的縮放系數為1.5:

第五章:尺寸處理(1)

WhatSize顯示的高度不包括螢幕底部的工作列。 螢幕對角線為12“,分辨率為144 DPI。

有關WhatSize程式本身的一些注意事項:

WhatSize在其構造函數中建立一個Label并在事件處理函數中設定Text屬性。這不是寫這樣一個程式的唯一方法。該程式可以使用SizeChanged處理程式來建立一個全新的Label,并将新的Label設定為頁面的内容,在這種情況下,以前的Label将變為未引用并是以有資格進行垃圾回收。但是在這個程式中創造新的視覺元素是不必要和浪費的。這是最好的方案

隻建立一個Label視圖,隻需設定Text屬性以訓示頁面的新大小。

監控尺寸變化是Xamarin.Forms應用程式可以檢測方向變化而不需要擷取平台特定資訊的唯一方式。寬度是否大于高度?那是風景。否則,它是肖像。

預設情況下,Xamarin.Forms解決方案的Visual Studio和Xamarin Studio模闆支援所有三個平台的裝置方向更改。如果您想禁用方向更改 - 例如,如果您的應用程式在縱向或橫向模式下效果不佳,則可以這樣做。

對于iOS,首先在Visual Studio或Xamarin Studio中顯示Info.plist的内容。在“iPhone部署資訊”部分中,使用“支援的裝置方向”區域指定允許的方向。

對于Android,在MainActivity.cs檔案的MainActivity類的Activity屬性中,添加:

或者

由解決方案模闆生成的Activity屬性包含一個ConfigurationChanges參數,該參數也指向螢幕方向,但ConfigurationChanges的用途是禁止在手機方向或螢幕大小更改時重新啟動活動。

對于兩個Windows Phone項目,要使用的類和枚舉位于Windows -.Graphics.Display命名空間中。 在MainPage.xaml.cs檔案的MainPage構造函數中,将靜态DisplayInformation.AutoRotationPreferences屬性設定為DisplayOrientations枚舉的一個或多個成員,并将其與C#按位或運算結合使用。 要将程式限制為橫向或縱向,請使用:

繼續閱讀