學習目標
- Slider & 詭異的最小最大值
- Stepper
15 章主要在介紹 Xamarin 的互動元件 (輕鬆但繁瑣的一章啊...)
Button 就屬於互動元件。
Button 就屬於互動元件。
而本次要讓大家認識的有八種 ViewElement,分別列出對應的資料型態:
Data Type
|
Views
|
Double
|
Slider,
Stepper
|
Boolean
|
Switch
|
String
|
Entry,
Editor, SearchBar
|
DateTime
|
DatePicker,
TimePicker
|
共會分成四個小節來介紹,先從 Slider 開始。
Slider
Xamarin.Forms Slider 是一個水平的拖曳條,擁有最小值(在左邊)和最大值(在右邊)
(Xamarin.Forms 無提供垂直的 Slider)
(Xamarin.Forms 無提供垂直的 Slider)
每個平台顯示的 Slider 都有些微的不同,但使用方式大致一樣,可以簡單的用拖曳的方式控制資料。
Slider 定義了三個為 double 的公用屬性,Minimum, Maximum 和 Value,當 Value 改變時會去觸發 ValueChanged 事件。
以下是簡易的 Slider Demo Code,可以看到初始指標會在最左邊,拖曳時 Label 顯示值:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SliderDemo.SliderDemoPage"> <StackLayout Padding="10, 0"> <Slider VerticalOptions="CenterAndExpand" ValueChanged="OnSliderValueChanged" /> <Label x:Name="label" FontSize="Large" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
注意:不要設定 Slider 的 HorizontalOptions ,除非你有設定 WidthRequest,不然 Slider 會變得非常小。
.cs:
public partial class SliderDemoPage : ContentPage { public SliderDemoPage() { InitializeComponent(); } void OnSliderValueChanged(object sender, ValueChangedEventArgs args) { label.Text = String.Format("Slider = {0}", args.NewValue); } }
Args 定義了 OldValue 和 NewValue 這兩個 double 屬性可以取得並使用。
但這不是取得 Slider 值的唯一方法,也可以像下面的程式碼:
但這不是取得 Slider 值的唯一方法,也可以像下面的程式碼:
void OnSliderValueChanged(object sender, ValueChangedEventArgs args) { Slider slider = (Slider)sender; label.Text = String.Format("Slider = {0}", slider.Value); }
當然也可以設定 Minimum 和 Maxmum 任何正負的數值來限制範圍,
像底下程式碼,Slider 的範圍就是 0 ~ 100:
But... 當你要設定 Slider 的範圍從 1~100 時,如下:
程式執行後,會拋出例外 ArgumentException : Value was an invalid value for Minimum,導致執行錯誤 (畫面一片空白啊)。
像底下程式碼,Slider 的範圍就是 0 ~ 100:
<Slider ValueChanged="OnSliderValueChanged" Maximum="100" VerticalOptions="CenterAndExpand" />
But... 當你要設定 Slider 的範圍從 1~100 時,如下:
<Slider ValueChanged="OnSliderValueChanged" Minimum="1" Maximum="100" VerticalOptions="CenterAndExpand" />
程式執行後,會拋出例外 ArgumentException : Value was an invalid value for Minimum,導致執行錯誤 (畫面一片空白啊)。
這也是我覺得很詭異的地方... 簡單的設定最小最大值,卻如此地不人性...
Slider 的詭異設定
上面的錯誤是因為物件在初始化時,會先將 Maximum 值預設為 1,等到程式碼開始逐行執行,遇到 Minimum 設定為 1 時
此時 Minimun == Maximun,系統就會發出例外錯誤,因為 Slider 有一個規則,Maximum 的值一定要大於 Minimun。
邏輯上來說,解決這問題最簡單的方法就是先設定 Maximun:
But
執行後又會出現另一個錯誤,在 ValueChanged 內發生 NullReferenceException
這是因為當 Minimum 值設定為 1 時,會去觸發 ValueChanged 事件時,而 ValueChanged 內的 Label 還未被初始化,所以跳出例外錯誤。
不論如何,最簡單的解法就是將 ValueChanged 方法往後移:
開發者表示:乾。
Slider 其他範例
這邊來看一支利用 Slider 控制 Label 透明度的程式
畫面上有兩個 Label,在 Slider 拖曳時可以看到其透明度的更改:
.cs :
Stepper
Stepper 和 Slider 很像,有 Minimum 和 Maximum 可以設定,也有 ValueChanged 事件可以觸發。
而與 Slidder 不一樣的是 Increment 屬性 (每次的增量) 預設值為 1。
以下程式碼展示如何利用 Stepper 去更改 Button 的 border width:
*Oplatform 寫法已更改,請參考此篇文章
Slider 的詭異設定
上面的錯誤是因為物件在初始化時,會先將 Maximum 值預設為 1,等到程式碼開始逐行執行,遇到 Minimum 設定為 1 時
此時 Minimun == Maximun,系統就會發出例外錯誤,因為 Slider 有一個規則,Maximum 的值一定要大於 Minimun。
邏輯上來說,解決這問題最簡單的方法就是先設定 Maximun:
<Slider ValueChanged="OnSliderValueChanged" Maximum="100" Minimum="1" VerticalOptions="CenterAndExpand" />
But
執行後又會出現另一個錯誤,在 ValueChanged 內發生 NullReferenceException
這是因為當 Minimum 值設定為 1 時,會去觸發 ValueChanged 事件時,而 ValueChanged 內的 Label 還未被初始化,所以跳出例外錯誤。
不論如何,最簡單的解法就是將 ValueChanged 方法往後移:
<Slider Maximum="100" Minimum="1" ValueChanged="OnSliderValueChanged" VerticalOptions="CenterAndExpand" />
開發者表示:乾。
Slider 其他範例
這邊來看一支利用 Slider 控制 Label 透明度的程式
畫面上有兩個 Label,在 Slider 拖曳時可以看到其透明度的更改:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="TextFade.TextFadePage" Padding="10, 0, 10, 20"> <StackLayout> <AbsoluteLayout VerticalOptions="CenterAndExpand"> <!-- Label 1 --> <Label x:Name="label1" Text="TEXT" FontSize="Large" AbsoluteLayout.LayoutBounds="0, 0.5" AbsoluteLayout.LayoutFlags="PositionProportional" /> <!-- Label 2 --> <Label x:Name="label2" Text="FADE" FontSize="Large" Opacity="0" AbsoluteLayout.LayoutBounds="0, 0.5" AbsoluteLayout.LayoutFlags="PositionProportional" /> </AbsoluteLayout> <Slider ValueChanged="OnSliderValueChanged" /> </StackLayout> </ContentPage>
.cs :
public partial class TextFadePage : ContentPage { public TextFadePage() { InitializeComponent(); } void OnSliderValueChanged(object sender, ValueChangedEventArgs args) { AbsoluteLayout.SetLayoutBounds(label1, new Rectangle(args.NewValue, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize)); AbsoluteLayout.SetLayoutBounds(label2, new Rectangle(args.NewValue, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize)); //更改透明度 label1.Opacity = 1 - args.NewValue; label2.Opacity = args.NewValue; } }
Stepper
Stepper 和 Slider 很像,有 Minimum 和 Maximum 可以設定,也有 ValueChanged 事件可以觸發。
而與 Slidder 不一樣的是 Increment 屬性 (每次的增量) 預設值為 1。
以下程式碼展示如何利用 Stepper 去更改 Button 的 border width:
*Oplatform 寫法已更改,請參考此篇文章
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="StepperDemo.StepperDemoPage"> <StackLayout> <!--Button--> <Button x:Name="button" Text=" Sample Button" FontSize="Large" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"> <Button.BackgroundColor> <OnPlatform x:TypeArguments="Color" Android="#404040" /> </Button.BackgroundColor> <Button.BorderColor> <OnPlatform x:TypeArguments="Color" Android="#C0C0C0" WinPhone="Black" /> </Button.BorderColor> </Button> <StackLayout VerticalOptions="CenterAndExpand"> <StackLayout Orientation="Horizontal" HorizontalOptions="Center"> <StackLayout.Resources> <ResourceDictionary> <Style TargetType="Label"> <Setter Property="FontSize" Value="Medium" /> </Style> </ResourceDictionary> </StackLayout.Resources> <Label Text="Button Border Width =" /> <Label x:Name="label" /> </StackLayout> <!--Stepper--> <Stepper x:Name="stepper" Maximum="10" ValueChanged="OnStepperValueChanged" HorizontalOptions="Center" /> </StackLayout> </StackLayout> </ContentPage>
.cs :
執行結果:public partial class StepperDemoPage : ContentPage { public StepperDemoPage() { InitializeComponent(); // Initialize display. OnStepperValueChanged(stepper, null); } void OnStepperValueChanged(object sender, ValueChangedEventArgs args) { Stepper stepper = (Stepper)sender; button.BorderWidth = stepper.Value; label.Text = stepper.Value.ToString("F0"); } }
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。