學習目標
- StackLayout - 物件堆疊排放
- ScrollView - 畫面捲動
- Expand 屬性在 StackLayout 內的使用
如果你已經拜讀完 三.壹 章,或許你會很興奮的開啟 VisualStudio ,接著把全部的顏色列出來寫在不同的 Lable 放到 ContentPage 內。
BUT,就是這個 BUT,會發現全部的 Label 都疊在同一個位子上...
小弟我寫網頁多年... textbox、div、button,物件不是放到畫面上就會自己往後排隊放好嗎...?
Xamarin.Forms 物件的排版有一些特定的 "畫板" 需要使用:
- AbsoluteLayout
- Grid
- RelativeLayout
- StackLayout
這一小節先來介紹 StackLayout。
顧名思義,StackLayout 就像是堆積物品一樣,將物件在畫面上一件一件疊上去,而 StackLayout 的順序可以是 從上到下 或 從左到右。
StackLayout 有兩個屬性:
- Orientation,可設定為 Vertical (預設) 或是 Horizontal
- Spacing of type double,預設值為 6.0
底下來看程式碼,這邊自己手動設定一組 Tuple<Color, string> 陣列資料,再用迴圈將
每筆資料加入 StackLayout 內:
每筆資料加入 StackLayout 內:
class ColorLoopPage : ContentPage { public ColorLoopPage() { var colors = new[] { new { value = Color.White, name = "White" }, new { value = Color.Silver, name = "Silver" }, new { value = Color.Gray, name = "Gray" }, new { value = Color.Black, name = "Black" }, new { value = Color.Red, name = "Red" }, new { value = Color.Maroon, name = "Maroon" }, new { value = Color.Yellow, name = "Yellow" }, new { value = Color.Olive, name = "Olive" }, new { value = Color.Lime, name = "Lime" }, new { value = Color.Green, name = "Green" }, new { value = Color.Aqua, name = "Aqua" }, new { value = Color.Teal, name = "Teal" }, new { value = Color.Blue, name = "Blue" }, new { value = Color.Navy, name = "Navy" }, new { value = Color.Pink, name = "Pink" }, new { value = Color.Fuchsia, name = "Fuchsia" }, new { value = Color.Purple, name = "Purple" } }; StackLayout stackLayout = new StackLayout(); foreach (var color in colors) { stackLayout.Children.Add(new Label { Text = color.name, TextColor = color.value, FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) }); } Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5); Content = stackLayout; } }執行結果:
BUT,會發現 Android 或 WP 有一些 Label 因為數量太多被擠出螢幕外了...
當然你可以試著把字縮小或是設定 Spacing = 0 讓每個 Label 無間距的靠在一起,這樣消失的 Label 就有機會出現在螢幕內...
但我們還是將 StackLayout 放到 ScrollView 內,讓物件可以上下滑動比較實在...
* StackLayout 的高度會自動調整和內部所有物件加起來的高度一樣,所以一般來說我們不會特地對物件設定 VerticalOptions。
ScrollView
書上這裡有介紹 typeof 的用法,這邊也提一下,因為等等程式碼會用到...
在 .NET 內,你可以利用 typeof 運算式取得任何類別或是結構 (Structure)。
舉例來說,typeof(Color) 就會回傳一個類別為 Type 的 Color 結構。
聽不懂沒關係,總之,你可以用迴圈配合方法將所有 Color 取出來...
看程式碼了解一下...
這支程式碼利用 typeof 將所有 Color 取出後,會利用 CreateColorLabel() 產生有顏色的 Label 並逐一塞進 StackLayout 內,再將此 StackLayout 放到 ScrollView。
而這 CreateColorLabel() 方法內會去計算 Label 背景色該是黑色還白色,讓 Label 文字更明顯。
執行後就能上下滑看看了~
Expand
每個 VisualElement 都能去設定其 VerticalOptions 和 HorizontalOptions,在早一點的章節
(二.貳)畫面位移 & 物件置中 就有提到過。
當然你可以試著把字縮小或是設定 Spacing = 0 讓每個 Label 無間距的靠在一起,這樣消失的 Label 就有機會出現在螢幕內...
但我們還是將 StackLayout 放到 ScrollView 內,讓物件可以上下滑動比較實在...
* StackLayout 的高度會自動調整和內部所有物件加起來的高度一樣,所以一般來說我們不會特地對物件設定 VerticalOptions。
ScrollView
書上這裡有介紹 typeof 的用法,這邊也提一下,因為等等程式碼會用到...
在 .NET 內,你可以利用 typeof 運算式取得任何類別或是結構 (Structure)。
舉例來說,typeof(Color) 就會回傳一個類別為 Type 的 Color 結構。
聽不懂沒關係,總之,你可以用迴圈配合方法將所有 Color 取出來...
看程式碼了解一下...
public class ReflectedColorsPage : ContentPage { public ReflectedColorsPage() { StackLayout stackLayout = new StackLayout(); // Loop through the Color structure fields. foreach (FieldInfo info in typeof(Color).GetRuntimeFields()) { // Skip the obsolete (i.e. misspelled) colors. if (info.GetCustomAttribute<ObsoleteAttribute>() != null) continue; if (info.IsPublic && info.IsStatic && info.FieldType == typeof(Color)) { stackLayout.Children.Add( CreateColorLabel((Color)info.GetValue(null), info.Name)); } } // Loop through the Color structure properties. foreach (PropertyInfo info in typeof(Color).GetRuntimeProperties()) { MethodInfo methodInfo = info.GetMethod; if (methodInfo.IsPublic && methodInfo.IsStatic && methodInfo.ReturnType == typeof(Color)) { stackLayout.Children.Add( CreateColorLabel((Color)info.GetValue(null), info.Name)); } } Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5); // Put the StackLayout in a ScrollView. Content = new ScrollView { Content = stackLayout }; } Label CreateColorLabel(Color color, string name) { Color backgroundColor = Color.Default; if (color != Color.Default) { // Standard luminance calculation. double luminance = 0.30 * color.R + 0.59 * color.G + 0.11 * color.B; backgroundColor = luminance > 0.5 ? Color.Black : Color.White; } // Create the Label. return new Label { Text = name, TextColor = color, FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), BackgroundColor = backgroundColor }; } }
這支程式碼利用 typeof 將所有 Color 取出後,會利用 CreateColorLabel() 產生有顏色的 Label 並逐一塞進 StackLayout 內,再將此 StackLayout 放到 ScrollView。
而這 CreateColorLabel() 方法內會去計算 Label 背景色該是黑色還白色,讓 Label 文字更明顯。
執行後就能上下滑看看了~
Expand
每個 VisualElement 都能去設定其 VerticalOptions 和 HorizontalOptions,在早一點的章節
(二.貳)畫面位移 & 物件置中 就有提到過。
其中有四個 LayoutOptions 唯讀屬性可以使用:
- LayoutOptions.Start
- LayoutOptions.Center
- LayoutOptions.End
- LayoutOptions.Fill (預設)
像上面 ReflectedColorsPage 程式,可以藉由 Label 黑色的背景觀察到, Label 在 StackLayout 左右寬度是 Fill 的。
這一小節要介紹的是另外四個屬性:
- LayoutOptions.StartAnd
- LayoutOptions.CenterAndExpand
- LayoutOptions.EndAndExpand
- LayoutOptions.FillAndExpand
*要注意的是,這四個屬性只有在 StackLayout 內有效果。
- StackLayout 的內容物件總高度不能大於 StackLayout 的高度。
- StackLyout 不能設定 VerticalOptions 為 Start、Center 或 End。
- StackLayout 內至少有一個子項目的 VerticalOptions 設定為 Expand。
完成以上條件就能觸發 Expand...而 Expand 的功能就是平均分配物件在 StackLayout 的配置的空間。
public class VerticalOptionsDemoPage : ContentPage { public VerticalOptionsDemoPage() { Color[] colors = { Color.Yellow, Color.Blue }; int flipFlopper = 0; // Create Labels sorted by LayoutAlignment property. IEnumerable
執行結果:可以看到四個黃色的 Expand Label 平均在畫面上分配的狀況。
*最後再提醒一下,Expand 在其他 Layout 是無效的! 只能用在 StackLayout 內!
感謝作者整理的教學系列文。
回覆刪除我發現ScrollView裡面的程式碼
if (info.GetCustomAttribute() != null)
continue;
這句會有錯,看了你下一篇裡面貼的原文電子書,要下面這樣才可以編譯
if (info.GetCustomAttribute < ObsoleteAttribute> () != null)
continue;
好像< ObsoleteAttribute> 沒空一格,字會被吃掉
感謝你喔!! 文章已經修正!!
刪除請問羅根大大,您在做這教學時,所看的書是哪本書呢?能否提供參考?小弟在此感激不盡
回覆刪除YOOOOOOO!!!! 你一定沒從第一章開始看XD
刪除教學都是微軟官方的原文電子書來的喔,大概花了兩年的時間才把這本看過一次並做成教學,
有任何問題也歡迎從粉絲團私訊給我
https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/
Device.OnPlatform(20, 0, 0)
回覆刪除有關於這個語法 在vs2017 上表示好像過時了
有更好的寫法嗎?
http://www.loganedge.tw/2018/01/xamarinforms-oplatform.html 這篇有詳解喔,有問題再問我
刪除原來如此 要換成SWITCH CASE
刪除又讓我想起不好的回憶XDDD
謝謝^^
Xamarin.Fomrs 能支援的開發平台越來越多了,最近的版本狂推 Mac os app,我猜為了擴充性才改成那樣吧
刪除最近才剛接觸Xamarin 很多功能都還不了解XD
刪除