學習目標
- Frame - 自帶邊緣陰影的容器。
- BoxView - 可填滿顏色的矩形。
- 如何讀取文字 (.txt) 實體檔。
這小節介紹兩個滿常用到的畫面元件,Frame 和 BoxView。
先來介紹 Frame:
Frame
Frame 是一個與內部元件預設間隔 20 (padding = 20) ,自帶邊緣陰影特效的容器物件,有幾個常用的屬性可以設定:
- HasShadow - 預設 True
- BackgroundColor
- OutlineColor
看名字就知道這些屬性在設定什麼了吧...
不論是 Frame 或 BoxView,如沒有特別指定寬高,或是設定 LayoutOptions、HorizontalOptions,預設都是 LayoutOptions.Fill (填滿畫面)。
public class FramedTextPage : ContentPage { public FramedTextPage() { Padding = new Thickness(20); Content = new Frame { OutlineColor = Color.Accent, Content = new Label { Text = "I've been framed!", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center } }; } }
執行結果如下:可以觀察到 Farme 預設填滿整個畫面。
接著我們改把 Frame 置中,可以觀察到 Frame 內邊緣和 Label 間隔 20 單位。
public class FramedTextPage : ContentPage { public FramedTextPage() { Padding = new Thickness(20); Content = new Frame { OutlineColor = Color.Accent, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Content = new Label { Text = "I've been framed!", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) } }; } }
再來改一下顏色設定:
public class FramedTextPage : ContentPage { public FramedTextPage() { BackgroundColor = Color.Aqua; Content = new Frame { OutlineColor = Color.Black, BackgroundColor = Color.Yellow, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Content = new Label { Text = "I've been framed!", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), FontAttributes = FontAttributes.Italic, TextColor = Color.Blue } }; } }
執行結果:
BoxView
用法簡單,直接看程式:
public class SizedBoxViewPage : ContentPage { public SizedBoxViewPage() { Content = new BoxView { Color = Color.Accent }; } }
執行結果:同樣預設是填滿畫面,iOS 甚至連最上方的 Bar 一起填滿。
將 BoxView 置中一下:
public class SizedBoxViewPage : ContentPage { public SizedBoxViewPage() { Content = new BoxView { Color = Color.Accent, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center }; } }
執行結果:可以觀察到 BoxView 有基本的寬高, 40 單位。
這邊要提到兩個重要的屬性:
- WidthRequest
- HeightRequest
BoxView 就是將這兩個屬性預設為 40 單位。
為什麼會說這兩個屬性重要,因為畫面元件 ( VisualElement ) 其實也有 Width 和 Height 這兩個 唯獨 屬性,但:
物件寬高要設定 WidthRequest 和 HeightRequest 才有效!
一般來說 WidthRequest 和 HeightRequest 預設是 -1 (代表無定義),而這兩個屬性真正的涵義是你希望(或要求)這個物件的寬高。
*原因,是因為當你針對畫面元件 (VisualElement) 設定 HorizontalOptions 或 VerticalOptions 時,WidthRequest 和 HeightRequest 會自動失效 (所以稱之為要求的寬高)。
舉例來說,若你設定了 LayoutOptions.Fill,VisualElement 會填滿畫面而不鳥 WidthRequest 或 HeightRequest 的設定。
來設定下寬高:
public class SizedBoxViewPage : ContentPage { public SizedBoxViewPage() { BackgroundColor = Color.Pink; Content = new BoxView { Color = Color.Navy, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, WidthRequest = 200, HeightRequest = 100 }; } }
執行結果:
書上 p.81 ~ 82 有個不錯的程式,讓你更加了解如何利用 Stacklayout、Frame 和 BoxView 的排版,這裡只貼上執行結果,有興趣看程式就自行看原文電子書~
https://download.xamarin.com/developer/xamarin-forms-book/XamarinFormsBook-Ch04-Apr2016.pdf
讀取 .txt 檔
小節最後要實作一個簡易的電子書程式。
本支程式會先讀出 .txt 檔案後,將第一行文字設定為固定於頂端的標題 Label,而標題下方的內容文字可以捲動閱讀。
讀取 .txt 檔最簡單的方式就是將檔案放在 PCL 的內嵌資源內,如下步驟:
- 於 VisualStudio 專案右鍵 → 新增資料夾,命名為 Texts
- 右鍵 Texts 資料夾,加入 → 現有項目 (選取 .txt 檔案)
- 右鍵檔案 → 屬性 → 更改建置動作 (Build Action) 為內嵌資源 (Embedded Resourc
- 建置專案
以上四個步驟就能將 txt 檔內嵌到 dll 檔案內當作資源使用了。
程式方面,我們將用 Assembly 類別提供的 GetManifestResourceStream 方法來獲取這個資源。
Assembly 可以如下宣告為物件使用:
Assembly assembly = GetType().GetTypeInfo().Assembly;
接著要注意的是使用 GetManifestResourceStream 時需要帶入的參數 Resource ID,這參數組成的格式如下:
Namespace.資料夾名.檔名.副檔名底下範例就是:BlackCat.Texts.TheBlackCat.txt
GetManifestResourceStream 執行後會回傳一個 Stream 物件,我們就能用 .NET 的 StreamReader 來讀取物件內的每一行文字。
來看程式碼:
class BlackCatPage : ContentPage { public BlackCatPage() { StackLayout mainStack = new StackLayout(); StackLayout textStack = new StackLayout { Padding = new Thickness(5), Spacing = 10 }; // Get access to the text resource. Assembly assembly = GetType().GetTypeInfo().Assembly; string resource = "BlackCat.Texts.TheBlackCat.txt"; using (Stream stream = assembly.GetManifestResourceStream(resource)) { using (StreamReader reader = new StreamReader(stream)) { bool gotTitle = false; string line; // Read in a line (which is actually a paragraph). while (null != (line = reader.ReadLine())) { Label label = new Label { Text = line, // Black text for ebooks! TextColor = Color.Black }; if (!gotTitle) { // Add first label (the title) to mainStack. label.HorizontalOptions = LayoutOptions.Center; label.FontSize = Device.GetNamedSize(NamedSize.Medium, label); label.FontAttributes = FontAttributes.Bold; mainStack.Children.Add(label); gotTitle = true; } else { // Add subsequent labels to textStack. textStack.Children.Add(label); } } } } // Put the textStack in a ScrollView with FillAndExpand. ScrollView scrollView = new ScrollView { Content = textStack, VerticalOptions = LayoutOptions.FillAndExpand, Padding = new Thickness(5, 0), }; // Add the ScrollView as a second child of mainStack. mainStack.Children.Add(scrollView); // Set page content to mainStack. Content = mainStack; // White background for ebooks! BackgroundColor = Color.White; // Add some iOS padding for the page. Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0); } }
執行結果:
程式內要注意的還有排版的階層關係。最外面一層 mainStack,包含兩個子項目,標題 Label 和 內容 ScrollViewt。
利用外層的 Stacklayout 將這兩個子項目做堆疊排版,就能達到標題 Label 固定於最上方的效果。
請問一下,我resource id要打成這樣 string resource = "BlackCat.Droid.Texts.BlackCat.txt"; 才能讀到檔耶
回覆刪除這是為什麼??
謝謝
檔案是放在PCL專案內嗎?
刪除感謝回覆,我後來解出來了,原來選到了Shared Project
回覆刪除謝謝哦~
嗯嗯解決就好!
刪除我想請問一下,我按照以上的步驟後,還是讀檔失敗,以下是我的error msg,我有截圖請問我要怎放上來,感謝(初入xamarin的菜逼)
回覆刪除Unhandled Exception:
System.ArgumentNullException: Value cannot be null.
Parameter name: stream
歡迎入坑XD
刪除看起來是沒有讀到檔案造成stream是null產生的錯誤
也歡迎直接用fb粉絲團向我問問題