學習目標
- 了解 Xamarin 的單位 Device-independent Units
- SizeChanged 事件
- 如何判斷目前手機方向,portrait 或 landscape
- Device.StartTimer 方法
前四章已經有出現一些使用單位的屬性:
- iOS 狀態列高度是 20
- BoxView 預設寬高是 40
- Frame 內緣的間距 (Padding) 是 20
- StackLayout 的物件間距 (Spacing) 是 6
這些尺寸的 "單位" 到底是什麼??
這小節讓我們從最常見的螢幕單位 - DPI,來討論為何我們在 Xamarin.Forms 需要一個特殊的單位,原文書上有更多詳細的解釋 (更多英文),有興趣的可以翻來看看。
DPI & Device-independent Units
DPI (Dots per inch),意思是每一英吋下螢幕可顯示的輸出點 (points) 數目,(point 可以想成手機螢幕硬體顯示單位)。
而我們常用的成像單位為像素點 (pixel),伴隨著解析度越高,每一螢幕輸出點 (point) 就能顯示越多的 pixel。
舉例來說:
3.5 吋 的 iPhone4,螢幕像素點為 640 x 960 pixel,DPI 約為 320,一個顯示點 (point) 內會包含 2 個 pixel。
3.5 吋 的 iPhone4,螢幕像素點為 640 x 960 pixel,DPI 約為 320,一個顯示點 (point) 內會包含 2 個 pixel。
而 5.5 吋的 iPhone 6 Plus,螢幕像素點為 1080 x 1920 pixel,DPI 約為 401,一個顯示點 (point) 內會包含 3 個 pixel。
重點就是,會因為各手機型號不同,而有不同尺寸的顯示單位。
Xamarin.Forms 為了方便且統一處理這些不同顯示尺寸的問題,幫我們定義了一個特殊單位,叫做 device-independent units。
device-independent units 會自動幫我們去處理不同手機螢幕輸出,而其解析度為:
- 一英吋 160 units
- 或是 一公分 64 units
每個 Visual Element 類別都定義了 Width 和 Height,這兩個屬性的初始值為 -1,表示無定義,接著若程式有設定 HorizontalOptions 或是 VerticalOptions,才會去更改 Width 和 Height 的值。
若要自行設定 Visual Element 的寬或高,要設定 WidthRequest 或 HeightRequest,Width 和 Height 為唯讀屬性 (系統用,只可查詢不可更改)。
SizeChanged
每個 VisualElement 都定義了 SizeChanged 事件 ,當物件的寬或高發生改變時就會觸發此事件,包括 Page 本身。
很單純的顯示 Page 寬和高:
public class WhatSizePage : ContentPage { Label label; public WhatSizePage() { label = new Label { FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; Content = label; SizeChanged += OnPageSizeChanged; } void OnPageSizeChanged(object sender, EventArgs args) { label.Text = String.Format("{0} \u00D7 {1}", Width, Height); } }
辨識手機方向為橫向 (landscape) 或直向 (portrait)
唯一方法就是判斷其寬跟高的關係,當寬大於高時就是橫向 (landscape),反之為直向 (portrait)。
if( Width > Height )
{
...
}
往後的書上也會看到實際的程式範例,當我們要在不同方向時處理不同事情時,會將寬高判斷寫在 SizeChanged 內。
此外,若你想鎖定 App 方向時:
iOS:Visual Studio 內, iPhone Deployment Info 選項,選擇 Supported Device Orientations,就能指定 App 的方向。
Android:在 Droid 專案底下,MainActivity.cs 檔案內,Activity 加上
ScreenOrientation = ScreenOrientation.Landscape
或
ScreenOrientation = ScreenOrientation.Portrait
Device.StartTimer
Device 類別內有提供一個 StartTimer 方法可以使用,設定好間隔時間後,就能週期性的觸發事件。
且在 SizeChanged 事件時會去更改 Label 字體大小,讓畫面更...美觀:
這程式有三點要注意的:
執行結果:
當然,倒過來時文字會較大 (美觀~):
第五章我其實省略滿多東西... 只挑我覺得重要的部分來說明,有興趣的可以翻翻原文,這裡提供官方 PDF :
唯一方法就是判斷其寬跟高的關係,當寬大於高時就是橫向 (landscape),反之為直向 (portrait)。
if( Width > Height )
{
...
}
往後的書上也會看到實際的程式範例,當我們要在不同方向時處理不同事情時,會將寬高判斷寫在 SizeChanged 內。
此外,若你想鎖定 App 方向時:
iOS:Visual Studio 內, iPhone Deployment Info 選項,選擇 Supported Device Orientations,就能指定 App 的方向。
Android:在 Droid 專案底下,MainActivity.cs 檔案內,Activity 加上
ScreenOrientation = ScreenOrientation.Landscape
或
ScreenOrientation = ScreenOrientation.Portrait
Device.StartTimer
Device 類別內有提供一個 StartTimer 方法可以使用,設定好間隔時間後,就能週期性的觸發事件。
StartTimer 內要帶入的參數為 TimeSpan 類別。底下的範例程式,其功能為使用 Label 顯示目前時間,
且在 SizeChanged 事件時會去更改 Label 字體大小,讓畫面更...美觀:
public class FitToSizeClockPage : ContentPage { public FitToSizeClockPage() { Label clockLabel = new Label { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; Content = clockLabel; // Handle the SizeChanged event for the page. SizeChanged += (object sender, EventArgs args) => { // Scale the font size to the page width // (based on 11 characters in the displayed string). if (this.Width > 0) clockLabel.FontSize = this.Width / 6; }; // Start the timer going. Device.StartTimer(TimeSpan.FromSeconds(1), () => { // Set the Text property of the Label. clockLabel.Text = DateTime.Now.ToString("h:mm:ss tt"); return true; }); } }
這程式有三點要注意的:
- 間隔時間參數 TimeSpan. 的用法。
- 更改 Label.Text 的事件寫在 Lambda 語法內,而 Lambda 寫法的優點就是便於維護 (事件較靠近物件)。
- Device.StartTimer 內的事件要 return true,計時器才會繼續執行下一個週期。
執行結果:
當然,倒過來時文字會較大 (美觀~):
第五章我其實省略滿多東西... 只挑我覺得重要的部分來說明,有興趣的可以翻翻原文,這裡提供官方 PDF :
https://download.xamarin.com/developer/xamarin-forms-book/XamarinFormsBook-Ch05-Apr2016.pdf
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。