學習目標
- 第二個 Attached bindable propertie - LayoutFlagProperty
- XAML 寫法
- Overlays
延續上一小節的棋盤,
還記得當我們在 SizeChanged 時,會先去取得螢幕的寬高,再計算出方塊的大小。忘記了請看上圖...
如果... AbsoluteLayout 能自動幫我們計算方塊的大小...
沒錯... Xamarin 就是這麼貼心... 提供了另一個 Attached bindable propertie - LayoutFlagProperty
可讓程式依照 比例 自動計算物件的大小。
LayoutFlagProperty 有兩個靜態方法可用:
- GetLayoutFlags()
- SetLayoutFlags()
使用 SetLayoutFlags() 時,需先指定要做自動計算的元素,可指定的元素由 AbsoluteLayoutFlags 類別內選擇成員,共八種:
- None
- XProportional
- YProportional
- PositionProportional
- WidthProportional
- HeightProportional
- SizeProportional
- All
LayoutFlagProperty
用法如下:
absoluteLayout.SetLayoutFlags(view, AbsoluteLayoutFlags.All)
或是在新增物件時就帶入:
absoluteLayout.Children.Add(view, rect, AbsoluteLayoutFlags.All)
設定好 LayoutFlagProperty 後,就能在 Rectangle 指派 0 ~ 1 的值當做 比例,讓程式自動去計算在畫面上實際的大小。
來看範例,一樣是上一小節的棋盤程式,但我們使用 LayoutFlagProperty 自動換算方塊的 x, y, width, height:
*Oplatform 寫法已更改,請參考此篇文章
public class ChessboardProportionalPage : ContentPage { AbsoluteLayout absoluteLayout; public ChessboardProportionalPage() { absoluteLayout = new AbsoluteLayout { BackgroundColor = Color.FromRgb(240, 220, 130), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { // Skip every other square. if (((row ^ col) & 1) == 0) continue; BoxView boxView = new BoxView { Color = Color.FromRgb(0, 64, 0) }; //此處值都為 0 ~ 1 Rectangle rect = new Rectangle(col / 7.0, // x row / 7.0, // y 1 / 8.0, // width 1 / 8.0); // height //LayoutFlagsProperty absoluteLayout.Children.Add(boxView, rect, AbsoluteLayoutFlags.All); } } ContentView contentView = new ContentView { Content = absoluteLayout }; contentView.SizeChanged += OnContentViewSizeChanged; this.Padding = new Thickness(5, Device.OnPlatform(25, 5, 5), 5, 5); this.Content = contentView; } void OnContentViewSizeChanged(object sender, EventArgs args) { ContentView contentView = (ContentView)sender; double boardSize = Math.Min(contentView.Width, contentView.Height); absoluteLayout.WidthRequest = boardSize; absoluteLayout.HeightRequest = boardSize; } }
AbsoluteLayout and XAML
直接看範例了解 AbsoluteLayout 的 XAML 如何寫:
要注意的是 LayoutBounds 的寫法。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="AbsoluteXamlDemo.AbsoluteXamlDemoPage"> <AbsoluteLayout Padding="50"> <BoxView Color="Accent" AbsoluteLayout.LayoutBounds="20, 0, 5, 65" /> <Label Text="Stylish Header" FontSize="24" AbsoluteLayout.LayoutBounds="30, 25, AutoSize, AutoSize" /> </AbsoluteLayout> </ContentPage>
Overlays
AbsoluteLayout 最有用的功能之一大概就是這個…覆蓋畫面,並放上 ActivityIndicator (轉圈圈) 或是 ProgressBar (進度條),在等待進度完成前不讓使用者操作其他功能。
直接來看範例,畫面上有一顆 Button,和一個 放有 ProgressBar 的隱藏 ContentView。
XAML://本範例對照原文書有做刪減
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleOverlay.SimpleOverlayPage"> <AbsoluteLayout> <StackLayout AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All"> <!-- 觸發按鈕 --> <Button Text="Run 5-Second Job" FontSize="Large" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" Clicked="OnButtonClicked" /> </StackLayout> <!-- Overlay --> <ContentView x:Name="overlay" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" IsVisible="False" BackgroundColor="#C0808080" Padding="10, 0"> <ProgressBar x:Name="progressBar" VerticalOptions="Center" /> </ContentView> </AbsoluteLayout> </ContentPage>
.cs - 讓 ProgressBar 執行五秒~
public partial class SimpleOverlayPage : ContentPage { public SimpleOverlayPage() { InitializeComponent(); } void OnButtonClicked(object sender, EventArgs args) { // 顯示 overlay overlay.IsVisible = true; TimeSpan duration = TimeSpan.FromSeconds(5); DateTime startTime = DateTime.Now; // 使用 Timer,每 0.1 秒執行一次 Device.StartTimer(TimeSpan.FromSeconds(0.1), () => { // 計算進度條 現在時間 - 開始時間 / 所有時間 double progress = (DateTime.Now - startTime).TotalMilliseconds / duration.TotalMilliseconds; progressBar.Progress = progress; bool continueTimer = progress < 1; if (!continueTimer) { // 隱藏 overlay overlay.IsVisible = false; } return continueTimer; }); } }
執行結果:
原文書最後有用 AbsoluteLayout 寫兩個有趣的範例,從 p.362 開始~ 有興趣的可自行翻閱~
數位鐘:
不斷移動的 Label:
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。