適用於 Xamarin.iOS 的 MonoTouch.Dialog 簡介
MonoTouch.Dialog,稱為 MT。簡短來說,D 是一個快速的UI開發工具組,可讓開發人員使用資訊建置應用程式畫面和流覽,而不是建立檢視控制器、數據表等的Tedium。因此,它可大幅簡化UI開發和程式碼。 例如,請考慮下列螢幕快照:
下列程式代碼是用來定義整個畫面:
public enum Category
{
Travel,
Lodging,
Books
}
public class Expense
{
[Section("Expense Entry")]
[Entry("Enter expense name")]
public string Name;
[Section("Expense Details")]
[Caption("Description")]
[Entry]
public string Details;
[Checkbox]
public bool IsApproved = true;
[Caption("Category")]
public Category ExpenseCategory;
}
在 iOS 中使用資料表時,通常會有一噸重複的程式代碼。 例如,每次需要數據表時,都需要數據源才能填入該數據表。 在具有兩個透過流覽控制器連線的數據表型畫面的應用程式中,每個畫面都會共用許多相同的程序代碼。
MT。D 可將所有程式代碼封裝到一般 API,以建立數據表,以簡化該程式代碼。 然後,它會在該 API 之上提供抽象概念,讓宣告式對象系結語法更容易。 因此,MT 中有兩個 API 可供使用。D:
- 低階元素 API – 元素 API 是以建立代表畫面及其元件之元素的階層式樹狀結構為基礎。 Elements API 可讓開發人員在建立UI時最具彈性和控制力。 此外,Elements API 透過 JSON 提供宣告式定義的進階支援,這可讓伺服器產生令人難以置信的快速宣告,以及動態 UI 產生。
- 高階反映 API – 也稱為系結API ,其中類別會以 UI 提示加上批註,然後再標註 MT。D 會根據物件自動建立畫面,並提供畫面上顯示的內容(並選擇性編輯)與基礎對象支援之間的系結。 上述範例說明如何使用反映 API。 此 API 不會提供元素 API 所執行的精細控件,但藉由根據類別屬性自動建置元素階層,進一步降低複雜度。
MT。D 隨附一組大型內建 UI 元素來建立螢幕,但也辨識自定義元素和進階螢幕配置的需求。 因此,擴充性是內嵌至 API 的第一級功能。 開發人員可以擴充現有的元素或建立新的元素,然後順暢地整合。
此外,MT。D 內建許多常見的 iOS UX 功能,例如「提取重新整理」支援、異步影像載入和搜尋支援。
本文將全面探討如何使用 MT。D,包括:
- MT。D 元件 – 這會著重於了解構成 MT 的類別。D,讓能夠快速上手。
- 元素參考 – MT.D 內建元素的完整清單。
- 進階使用 方式 – 這涵蓋進階功能,例如提取以重新整理、搜尋、背景影像載入、使用LINQ建置元素階層,以及建立自定義元素、單元格和控制器以搭配MT.D使用。
設定 MT。D
MT。D 會與 Xamarin.iOS 一起散發。 若要使用它,請以滑鼠右鍵按兩下Visual Studio 2017或Visual Studio for Mac 中 Xamarin.iOS 專案的 [參考] 節點,然後新增 MonoTouch.Dialog-1 元件的參考。 然後,視需要在原始程式碼中新增 using MonoTouch.Dialog
語句。
瞭解 MT 片段。D
即使使用反映 API,MT 也是如此。D 會在幕後建立元素階層,就像是直接透過 Elements API 建立一樣。 此外,上一節所述的 JSON 支援也會建立 Elements。 因此,請務必對 MT.D 的組成部分有基本的瞭解。
MT。D 會使用下列四個部分來建置畫面:
- DialogViewController
- RootElement
- 區段
- Element
DialogViewController
DialogViewController 或 DVC 短期繼承自 UITableViewController
,因此代表含有數據表的畫面。 DVC 可以推送至流覽控制器,就像一般 UITableViewController 一樣。
RootElement
RootElement 是進入 DVC 之專案的最上層容器。 它包含區段,然後可以包含 Elements。 RootElement 不會轉譯;相反地,它們只是實際轉譯專案的容器。 RootElement 會指派給 DVC,然後 DVC 轉譯其子系。
區段
區段是表格中的一組儲存格。 如同一般數據表區段,它可以選擇性地擁有頁首和頁尾,可以是文字,甚至是自定義檢視,如下列螢幕快照所示:
元素
Element 代表數據表中的實際儲存格。 MT。D 隨附各種代表不同數據類型或不同輸入的 Elements。 例如,下列螢幕快照說明一些可用的元素:
深入瞭解區段和 RootElements
現在讓我們更詳細地討論 RootElements 和 Sections。
RootElements
至少需要一個 RootElement 才能啟動 MonoTouch.Dialog 程式。
如果 RootElement 是以 section/element 值初始化,則此值會用來尋找子元素,以提供組態摘要,這會在顯示右側呈現。 例如,下列螢幕快照顯示左側的表格,其中包含右側詳細數據畫面的標題“甜點”,以及所選沙漠的值。
根元素也可以在區段內使用,以觸發載入新的巢狀組態頁面,如上所示。 在此模式中使用時,提供的標題會在區段內轉譯時使用,也會當做子頁面的標題使用。 例如:
var root = new RootElement ("Meals") {
new Section ("Dinner") {
new RootElement ("Dessert", new RadioGroup ("dessert", 2)) {
new Section () {
new RadioElement ("Ice Cream", "dessert"),
new RadioElement ("Milkshake", "dessert"),
new RadioElement ("Chocolate Cake", "dessert")
}
}
}
};
在上述範例中,當用戶點選 「甜點」時,MonoTouch.Dialog 會建立新的頁面,並流覽至其根目錄為「甜點」,並具有三個值的單選群組。
在此特定範例中,無線電群組會在 [甜點] 區段中選取 [巧克力蛋糕],因為我們將值 “2” 傳遞給 RadioGroup。 這表示在清單上挑選第三個專案(零索引)。
呼叫 Add 方法或使用 C# 4 初始化表示式語法會新增區段。 會提供 Insert 方法,以使用動畫插入區段。
如果您使用 Group 實例建立 RootElement(而不是 RadioGroup),則 Section 中顯示的 RootElement 摘要值將會是具有 Group.Key 值相同索引鍵的所有布爾值和 CheckboxElements 的累計計數。
區段
區段是用來將畫面中的元素分組,而它們是唯一有效的 RootElement 直接子系。 區段可以包含任何標準元素,包括新的 RootElements。
內嵌在區段中的 RootElement 可用來流覽至更深層次的新層級。
區段可以有頁首和頁尾作為字串,或作為UIView。 一般而言,您只會使用字串,但若要建立自定義UI,您可以使用任何UIView作為頁首或頁尾。 您可以使用字串來建立字串,如下所示:
var section = new Section ("Header", "Footer");
若要使用檢視,只要將檢視傳遞至建構函式:
var header = new UIImageView (Image.FromFile ("sample.png"));
var section = new Section (header);
收到通知
處理 NSAction
MT。D 會將 NSAction
呈現為處理回呼的委派。
例如,假設您想要處理 MT.D 所建立之數據表單元格的觸控事件。 使用 MT 建立專案時。D,只要提供回呼函式,如下所示:
new Section () {
new StringElement ("Demo Callback", delegate { Console.WriteLine ("Handled"); })
}
擷取專案值
結合 Element.Value
屬性,回呼可以擷取在其他元素中設定的值。 例如,請考慮下列程式碼:
var element = new EntryElement (task.Name, "Enter task description", task.Description);
var taskElement = new RootElement (task.Name) {
new Section () { element },
new Section () { new DateElement ("Due Date", task.DueDate) },
new Section ("Demo Retrieving Element Value") {
new StringElement ("Output Task Description", delegate { Console.WriteLine (element.Value); })
}
};
此程式代碼會建立UI,如下所示。 如需此範例的完整逐步解說,請參閱 元素 API 逐步解說教學 課程。
當使用者按下底部數據表單元格時,匿名函式中的程式代碼會執行,將 element
實例 中的值寫入Visual Studio for Mac中的Application Output pad。
內建元素
MT。D 隨附一些稱為 Elements 的內建表格單元格專案。 這些元素可用來在表格單元格中顯示各種不同的類型,例如字串、浮點數、日期,甚至影像,只命名幾個。 每個元素都會負責適當地顯示數據類型。 例如,布爾項目會顯示切換其值的參數。 同樣地,float 元素會顯示滑桿來變更浮點數。
有更複雜的元素可支援更豐富的數據類型,例如影像和 html。 例如,html 元素會在選取時開啟 UIWebView 以載入網頁,並在表格單元格中顯示標題。
使用專案值
用來擷取使用者輸入的專案,會公開隨時保存專案目前值的公用 Value
屬性。 當使用者使用應用程式時,它會自動更新。
這是MonoTouch.Dialog所有元素的行為,但使用者建立的元素並非必要。
String 元素
StringElement
顯示表格單元格左邊的標題,以及儲存格右側的字串值。
若要使用 StringElement
作為按鈕,請提供委派。
new StringElement ("Click me", () => {
new UIAlertView("Tapped", "String Element Tapped", null, "ok", null).Show();
});
樣式字串專案
StyledStringElement
允許使用內建表格單元格樣式或自定義格式來呈現字串。
類別 StyledStringElement
衍生自 StringElement
,但可讓開發人員自定義一些屬性,例如 Font、文字色彩、背景儲存格色彩、折行模式、要顯示的行數,以及是否應該顯示配件。
多行元素
Entry 元素
如 EntryElement
名稱所示,是用來取得用戶輸入。 它支援一般字串或密碼,其中字元會隱藏。
它會使用三個值初始化:
- 將向用戶顯示之項目的標題。
- 佔位元文字 (這是為使用者提供提示的灰色文字)。
- 文字的值。
佔位元和值可以是 Null。 不過,需要標題。
在任何時間點,存取其 Value 屬性可以擷取的值 EntryElement
。
此外, KeyboardType
屬性可以在建立時設定為數據輸入所需的鍵盤類型樣式。 這可用來使用 下列 的 值 UIKeyboardType
來設定鍵盤:
- 數值
- 電話
- Url
- 電子郵件
布爾值專案
Checkbox 元素
Radio 元素
RadioElement
需要在 RadioGroup
中RootElement
指定 。
mtRoot = new RootElement ("Demos", new RadioGroup("MyGroup", 0));
RootElements
也用來協調無線電元素。 成員 RadioElement
可以跨越多個區段(例如,實作類似環形音調選取器,以及將自定義音調與系統鈴聲分開)。 摘要檢視會顯示目前選取的無線電元素。 若要使用此功能,請使用群組建構函式建立 RootElement
,如下所示:
var root = new RootElement ("Meals", new RadioGroup ("myGroup", 0));
中的 RadioGroup
組名是用來在包含頁面中顯示選取的值(如果有的話),而在此案例中為零的值是第一個選取專案的索引。
Badge 元素
Float 元素
Activity 元素
Date 元素
選取對應至 DateElement 的儲存格時,會顯示日期選擇器,如下所示:
Time 元素
選取對應至 TimeElement 的儲存格時,會顯示時間選擇器,如下所示:
DateTime 元素
選取對應至 DateTimeElement 的儲存格時,會顯示日期時間選擇器,如下所示:
HTML 元素
會在 HTMLElement
資料表數據格中顯示其 Caption
屬性的值。 選取 Whe, Url
指派給 元素的 會載入 控制項, UIWebView
如下所示:
Message 元素
載入更多元素
使用此元素可讓使用者在清單中載入更多專案。 您可以自定義一般和載入標題,以及字型和文字色彩。
UIActivity
指標會開始產生動畫效果,當使用者點選單元格時,就會顯示載入標題,然後NSAction
執行傳入建構函式的 。 完成中的程式代碼 NSAction
之後, UIActivity
指標會停止產生動畫效果,並再次顯示一般標題。
UIView 元素
此外,任何自定義 UIView
都可以使用 UIViewElement
來顯示。
Owner-Drawn 元素
這個元素必須子類別化,因為它是抽象類。 您應該覆寫 Height(RectangleF bounds)
應該傳回專案高度的方法,以及 Draw(RectangleF bounds, CGContext context, UIView view)
您應該使用內容和檢視參數,在指定範圍內執行所有自定義繪圖。 這個專案會繁重地將 子類別 UIView
化 ,並將它放在要傳回的單元格中,讓您只需要實作兩個簡單的覆寫。 您可以在 檔案中的 DemoOwnerDrawnElement.cs
範例應用程式中看到更好的範例實作。
以下是實作 類別的簡單範例:
public class SampleOwnerDrawnElement : OwnerDrawnElement
{
public SampleOwnerDrawnElement (string text) : base(UITableViewCellStyle.Default, "sampleOwnerDrawnElement")
{
this.Text = text;
}
public string Text { get; set; }
public override void Draw (RectangleF bounds, CGContext context, UIView view)
{
UIColor.White.SetFill();
context.FillRect(bounds);
UIColor.Black.SetColor();
view.DrawString(this.Text, new RectangleF(10, 15, bounds.Width - 20, bounds.Height - 30), UIFont.BoldSystemFontOfSize(14.0f), UILineBreakMode.TailTruncation);
}
public override float Height (RectangleF bounds)
{
return 44.0f;
}
}
JSON 元素
JsonElement
是 的RootElement
子類別,可擴充 RootElement
,以便從本機或遠端 URL 載入巢狀子系的內容。
JsonElement
是RootElement
可以以兩種形式具現化的 。 一個版本會 RootElement
建立 ,以視需要載入內容。 這些是使用 JsonElement
在結尾採用額外自變數的建構函式所建立,URL 會從下列位置載入內容:
var je = new JsonElement ("Dynamic Data", "https://tirania.org/tmp/demo.json");
另一種窗體會從本機檔案或您已剖析的現有 System.Json.JsonObject
檔案建立數據:
var je = JsonElement.FromFile ("json.sample");
using (var reader = File.OpenRead ("json.sample"))
return JsonElement.FromJson (JsonObject.Load (reader) as JsonObject, arg);
如需搭配 MT 使用 JSON 的詳細資訊。D,請參閱 JSON 元素逐步 解說 教學課程。
其他功能
提取重新整理支援
提取到重新整理是最初在 Tweetie2 應用程式中發現的視覺效果,在許多應用程式中成為熱門效果。
若要將自動提取重新整理支援新增至您的對話方塊,您只需要執行兩件事:將事件處理程式連結至使用者提取資料時收到通知,並在載入數據時通知 DialogViewController
,以回到其默認狀態。
連結通知很簡單;只要連線到 RefreshRequested
上的 DialogViewController
事件,如下所示:
dvc.RefreshRequested += OnUserRequestedRefresh;
然後,在方法 OnUserRequestedRefresh
上,您會將某些數據載入佇列、向 net 要求某些數據,或微調線程以計算數據。 載入資料之後,您必須通知 DialogViewController
新的資料已進入,以及將檢視還原為其默認狀態,您可以呼叫 ReloadComplete
來執行此動作:
dvc.ReloadComplete ();
搜尋支援
若要支援搜尋,請在 EnableSearch
上 DialogViewController
設定 屬性。 您也可以將 屬性設定 SearchPlaceholder
為在搜尋列中做為浮浮水印文字。
搜尋會將檢視的內容變更為用戶類型。 它會搜尋可見的欄位,並向用戶顯示這些欄位。 會 DialogViewController
公開三種方法,以程序設計方式起始、終止或觸發結果的新篩選作業。 以下列出這些方法:
StartSearch
FinishSearch
PerformFilter
系統是可延伸的,因此您可以視需要改變此行為。
背景影像載入
MonoTouch.Dialog 會 納入 TweetStation 應用程式的影像載入器。 此影像載入器可用來在背景載入影像、支援快取,並在載入影像時通知您的程序代碼。
它也會限制連出網路連線的數目。
映射載入器會在 類別中 ImageLoader
實作,您只需要呼叫 DefaultRequestImage
方法,您必須提供您要載入之映像的 URI,以及載入映像時要叫用的 IImageUpdated
介面實例。
例如,下列程式代碼會將影像從網址載入至 BadgeElement
:
string uriString = "http://some-server.com/some image url";
var rootElement = new RootElement("Image Loader") {
new Section() {
new BadgeElement( ImageLoader.DefaultRequestImage( new Uri(uriString), this), "Xamarin")
}
};
ImageLoader 類別會公開一個 Purge 方法,當您想要釋放目前在記憶體中快取的所有映射時,您可以呼叫此方法。 目前的程序代碼有 50 個影像的快取。 如果您想要使用不同的快取大小(例如,如果您預期影像太大,而 50 個影像會太大),您可以只建立 ImageLoader 的實例,並傳遞您想要保留在快取中的影像數目。
使用 LINQ 建立元素階層
透過巧妙使用 LINQ 和 C# 的初始化語法,LINQ 可用來建立元素階層。 例如,下列程式代碼會從某些字串陣列建立畫面,並透過傳入每個 StringElement
的匿名函式處理單元格選取:
var rootElement = new RootElement ("LINQ root element") {
from x in new string [] { "one", "two", "three" }
select new Section (x) {
from y in "Hello:World".Split (':')
select (Element) new StringElement (y, delegate { Debug.WriteLine("cell tapped"); })
}
};
這可以輕鬆地與 XML 資料存放區或資料庫中的數據結合,以建立幾乎完全來自數據的複雜應用程式。
擴充 MT。D
建立自定義元素
您可以從現有的 Element 繼承,或從根類別 Element 衍生,以建立您自己的元素。
若要建立您自己的 Element,您會想要覆寫下列方法:
// To release any heavy resources that you might have
void Dispose (bool disposing);
// To retrieve the UITableViewCell for your element
// you would need to prepare the cell to be reused, in the
// same way that UITableView expects reusable cells to work
UITableViewCell GetCell (UITableView tv);
// To retrieve a "summary" that can be used with
// a root element to render a summary one level up.
string Summary ();
// To detect when the user has tapped on the cell
void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path);
// If you support search, to probe if the cell matches the user input
bool Matches (string text);
如果您的元素可以有可變大小,您需要實 IElementSizing
作 介面,其中包含一個方法:
// Returns the height for the cell at indexPath.Section, indexPath.Row
float GetHeight (UITableView tableView, NSIndexPath indexPath);
如果您打算藉由呼叫base.GetCell(tv)
和自定義傳回的數據格來實作方法GetCell
,您也必須覆寫 CellKey
屬性以傳回元素唯一的索引鍵,如下所示:
static NSString MyKey = new NSString ("MyKey");
protected override NSString CellKey {
get {
return MyKey;
}
}
這適用於大部分的元素,但不適用於 StringElement
和 StyledStringElement
,因為這些元素會針對各種轉譯案例使用自己的索引鍵集。 您必須在這些類別中複寫程式代碼。
DialogViewControllers (DVC)
反映與元素 API 都使用相同的 DialogViewController
。 有時候,您會想要自定義檢視的外觀,或者您可能想要使用的 UITableViewController
一些功能,而不只是基本建立UI。
DialogViewController
只是 的UITableViewController
子類別,您可以使用自定義 的相同方式加以自定義UITableViewController
。
例如,如果您想要將清單樣式變更為 Grouped
或 Plain
,您可以在建立控制器時變更 屬性來設定此值,如下所示:
var myController = new DialogViewController (root, true) {
Style = UITableViewStyle.Grouped;
}
如需 的更進階自定義 DialogViewController
,例如設定其背景,您會將其子類別化並覆寫適當的方法,如下列範例所示:
class SpiffyDialogViewController : DialogViewController {
UIImage image;
public SpiffyDialogViewController (RootElement root, bool pushing, UIImage image)
: base (root, pushing)
{
this.image = image;
}
public override LoadView ()
{
base.LoadView ();
var color = UIColor.FromPatternImage(image);
TableView.BackgroundColor = UIColor.Clear;
ParentViewController.View.BackgroundColor = color;
}
}
另一個自定義點是 中的 DialogViewController
下列虛擬方法:
public override Source CreateSizingSource (bool unevenRows)
如果儲存格大小平均,或儲存格不平均,則這個方法應該會傳回 的子類別DialogViewController.Source
DialogViewController.SizingSource
。
您可以使用此覆寫來擷取任何 UITableViewSource
方法。 例如, TweetStation 會使用此專案來追蹤使用者何時捲動到頂端,並據以更新未讀取的推文數目。
驗證
元素不會提供驗證本身,因為適合網頁和傳統型應用程式的模型不會直接對應至iPhone互動模型。
如果您想要進行數據驗證,當使用者觸發輸入數據的動作時,應該執行此動作。 例如 ,頂端工具列上的 [完成 ] 或 [下一步 ] 按鈕,或一些 StringElement
用來做為按鈕的按鈕移至下一個階段。
這是您將執行基本輸入驗證的位置,或許更複雜的驗證,例如檢查使用者/密碼組合與伺服器的有效性。
您如何通知使用者錯誤是應用程式特定的。 您可以快顯 UIAlertView
或顯示提示。
摘要
本文涵蓋MonoTouch.Dialog的許多資訊。 它討論了 MT 如何的基本概念。D 可運作並涵蓋組成 MT.D 的各種元件。 它也會顯示 MT 所支援的各種元素和數據表自定義。D 並討論 MT 的方式。您可以使用自訂元素擴充 D。 此外,它也說明 MT 中的 JSON 支援。D,允許從 JSON 動態建立專案。