Введение в MonoTouch.Dialog для Xamarin.iOS
MonoTouch.Dialog, называемый MT. D для краткого представления — это быстрый набор средств разработки пользовательского интерфейса, позволяющий разработчикам создавать экраны приложений и навигацию с помощью информации, а не создавать контроллеры представления, таблицы и т. д. Таким образом, он обеспечивает значительное упрощение разработки пользовательского интерфейса и сокращения кода. Например, рассмотрим следующий снимок экрана:
Следующий код использовался для определения всего экрана:
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 часто возникает много репетитивный код. Например, каждый раз, когда требуется таблица, источник данных необходим для заполнения этой таблицы. В приложении с двумя табличными экранами, подключенными через контроллер навигации, каждый экран использует много одного кода.
МТ. D упрощает это путем инкапсулирования всего этого кода в универсальный API для создания таблиц. Затем он предоставляет абстракцию поверх этого API, который позволяет декларативным синтаксисом привязки объектов, что делает его еще проще. Таким образом, существует два API, доступных в MT. D:
- API элементов низкого уровня — API элементов основан на создании иерархического дерева элементов, представляющих экраны и их компоненты. API Элементов дает разработчикам большую гибкость и контроль при создании пользовательских интерфейсов. Кроме того, API Элементов имеет расширенную поддержку декларативного определения через JSON, что позволяет как для невероятно быстрого объявления, так и динамического создания пользовательского интерфейса с сервера.
- API отражения высокого уровня — также известный как API привязки, в котором классы аннотируются с указанием пользовательского интерфейса, а затем MT. D автоматически создает экраны на основе объектов и предоставляет привязку между отображаемыми (и необязательными изменениями) на экране и базовой резервной копией объекта. В приведенном выше примере показано использование API отражения. Этот API не предоставляет точное управление, которое выполняет API элементов, но снижает сложность еще больше, автоматически создавая иерархию элементов на основе атрибутов класса.
МТ. D поставляется с большим набором встроенных элементов пользовательского интерфейса для создания экрана, но также распознает необходимость настраиваемых элементов и расширенных макетов экрана. Таким образом, расширяемость — это первый класс, который выпекается в API. Разработчики могут расширить существующие элементы или создать новые, а затем легко интегрировать.
Кроме того, MT. D имеет ряд распространенных функций пользовательского интерфейса iOS, таких как поддержка "вытягивания к обновлению", асинхронная загрузка образов и поддержка поиска.
В этой статье вы узнаете, как работать с MT. D, включая:
- МТ. Компоненты D . Это будет сосредоточено на понимании классов, составляющих MT. D, чтобы быстро приступить к скорости.
- Справочник по элементам — полный список встроенных элементов MT.D.
- Расширенное использование — это дополнительные функции, такие как вытягивание к обновлению, поиск, загрузка фонового изображения, использование LINQ для построения иерархий элементов и создание пользовательских элементов, ячеек и контроллеров для использования с MT.D.
Настройка MT. D
МТ. D распространяется с помощью Xamarin.iOS. Чтобы использовать его, щелкните правой кнопкой мыши узел "Ссылки" проекта Xamarin.iOS в Visual Studio 2017 или Visual Studio для Mac и добавьте ссылку на сборку MonoTouch.Dialog-1. Затем добавьте using MonoTouch.Dialog
инструкции в исходный код по мере необходимости.
Общие сведения о кусках MT. D
Даже при использовании API отражения MT. D создает иерархию элементов под капотом так же, как если бы она была создана через API элементов напрямую. Кроме того, поддержка JSON, указанная в предыдущем разделе, также создает элементы. По этой причине важно иметь базовое понимание составляющих частей MT.D.
МТ. D создает экраны с помощью следующих четырех частей:
- DialogViewController
- RootElement
- Раздел
- Element
DialogViewController
Объект DialogViewController или DVC для короткого времени наследует и UITableViewController
поэтому представляет экран с таблицей. DvCs можно отправить на контроллер навигации так же, как обычный UITableViewController.
RootElement
RootElement — это контейнер верхнего уровня для элементов, которые отправляются в DVC. Он содержит разделы, которые затем могут содержать элементы. RootElements не отображаются; вместо этого они просто контейнеры для того, что на самом деле получает отрисовку. RootElement назначается DVC, а затем DVC отрисовывает дочерние элементы.
Section
Раздел — это группа ячеек в таблице. Как и в обычном разделе таблицы, он может при необходимости иметь верхний и нижний колонтитул, который может быть текстом или даже пользовательскими представлениями, как показано на следующем снимке экрана:
Элемент
Элемент представляет фактическую ячейку в таблице. МТ. D поставляется с широким спектром элементов, представляющих различные типы данных или различные входные данные. Например, на следующих снимках экрана показано несколько доступных элементов:
Дополнительные сведения о разделах и RootElements
Теперь рассмотрим RootElements и разделы более подробно.
RootElements
Для запуска процесса MonoTouch.Dialog требуется по крайней мере один RootElement.
Если rootElement инициализирован со значением раздела или элемента, то это значение используется для поиска дочернего элемента, который будет предоставлять сводку конфигурации, которая отображается справа от дисплея. Например, на снимок экрана ниже показана таблица слева с ячейкой, содержащей заголовок экрана сведений справа, "Десерт", а также значение выбранной пустыни.
Корневые элементы также можно использовать внутри разделов для активации загрузки новой вложенной страницы конфигурации, как показано выше. При использовании в этом режиме предоставленный заголовок используется во время отрисовки внутри раздела, а также используется в качестве заголовка для подпапки. Например:
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. Это означает, что выберите 3-й элемент в списке (нулевой индекс).
Вызов метода Add или использование синтаксиса инициализатора C# 4 добавляет разделы. Методы insert предоставляются для вставки разделов с анимацией.
При создании RootElement с экземпляром группы (вместо radioGroup) сводное значение RootElement при отображении в разделе будет совокупным числом всех логических элементов и флажков, имеющих тот же ключ, что и значение Group.Key.
Разделы
Разделы используются для группировки элементов на экране, и они являются единственными допустимыми прямыми дочерними элементами RootElement. Разделы могут содержать любой из стандартных элементов, включая новые rootElements.
RootElements, внедренные в раздел, используются для перехода к новому более глубокому уровню.
Разделы могут иметь верхние и нижние колонтитулы как строки, так и как UIViews. Как правило, вы будете использовать только строки, но для создания пользовательских UIs можно использовать любой UIView в качестве верхнего или нижнего колонтитула. Вы можете использовать строку для создания таких строк:
var section = new Section ("Header", "Footer");
Чтобы использовать представления, просто передайте представления конструктору:
var header = new UIImageView (Image.FromFile ("sample.png"));
var section = new Section (header);
Получение уведомлений
Обработка NSAction
МТ. 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); })
}
};
Этот код создает пользовательский интерфейс, как показано ниже. Полное пошаговое руководство по этому примеру см. в руководстве по API элементов.
Когда пользователь нажимает нижнюю ячейку таблицы, код в анонимной функции выполняется, записывая значение из element
экземпляра на панель вывода приложения в Visual Studio для Mac.
Встроенные элементы
МТ. D поставляется с рядом встроенных элементов ячейки таблицы, известных как Элементы. Эти элементы используются для отображения различных типов в ячейках таблицы, таких как строки, с плавающей запятой, даты и даже изображения, чтобы назвать лишь несколько. Каждый элемент заботится о правильном отображении типа данных. Например, логический элемент отобразит переключатель для переключения его значения. Аналогичным образом, элемент float будет отображать ползунок для изменения значения float.
Существуют еще более сложные элементы для поддержки более богатых типов данных, таких как изображения и html. Например, html-элемент, который откроет UIWebView для загрузки веб-страницы при выборе, отображает подпись в ячейке таблицы.
Работа со значениями элементов
Элементы, используемые для записи входных данных пользователя, предоставляют общедоступное Value
свойство, которое содержит текущее значение элемента в любое время. Он автоматически обновляется, так как пользователь использует приложение.
Это поведение для всех элементов, входящих в MonoTouch.Dialog, но не требуется для элементов, созданных пользователем.
Элемент String
Отображается StringElement
подпись в левой части ячейки таблицы и строковое значение в правой части ячейки.
Чтобы использовать StringElement
в качестве кнопки, укажите делегат.
new StringElement ("Click me", () => {
new UIAlertView("Tapped", "String Element Tapped", null, "ok", null).Show();
});
Элемент Styled String
Позволяет StyledStringElement
представлять строки с помощью встроенных стилей ячеек таблицы или настраиваемого форматирования.
Класс StyledStringElement
является производным от StringElement
, но позволяет разработчикам настраивать несколько свойств, таких как шрифт, цвет текста, цвет фона, цвет ячейки фона, режим разбиения строк, количество строк для отображения и необходимость отображения аксессуара.
Элемент Multiline
Элемент Entry
Как EntryElement
подразумевает имя, используется для получения входных данных пользователя. Он поддерживает обычные строки или пароли, где символы скрыты.
Он инициализирован с тремя значениями:
- Подпись для записи, которая будет отображаться пользователю.
- Замещающий текст (это серый текст, предоставляющий указание пользователю).
- Значение текста.
Заполнитель и значение могут иметь значение NULL. Тем не менее, подпись требуется.
В любой момент, доступ к свойству Value может получить значение EntryElement
.
Кроме того, KeyboardType
свойство можно задать во время создания для стиля типа клавиатуры, требуемого для записи данных. Это можно использовать для настройки клавиатуры с помощью значений, указанных UIKeyboardType
ниже.
- Числовое
- Номер телефона
- URL
- Эл. почта
Логический элемент
Элемент Checkbox
Элемент Radio
Требуется RadioElement
указывать в элементе RootElement
.RadioGroup
mtRoot = new RootElement ("Demos", new RadioGroup("MyGroup", 0));
RootElements
также используются для координации радиоэлеготов. Члены RadioElement
могут охватывать несколько разделов (например, реализовать что-то подобное селектору тонов кольца и отделять тоны пользовательского кольца от системных мелодий). В представлении сводки отображается выбранный в данный момент элемент радио. Для этого создайте RootElement
конструктор группы следующим образом:
var root = new RootElement ("Meals", new RadioGroup ("myGroup", 0));
Имя группы RadioGroup
используется для отображения выбранного значения на содержащей странице (если она есть) и значения, которое равно нулю в данном случае, является индексом первого выбранного элемента.
Элемент Индикатора событий
Элемент Float
Элемент Activity
Элемент Date
Если выбрана ячейка, соответствующая DateElement, средство выбора дат отображается, как показано ниже:
Time, элемент
При выборе ячейки, соответствующей TimeElement, отображается средство выбора времени, как показано ниже:
Элемент DateTime
Если выбрана ячейка, соответствующая DateTimeElement, средство выбора даты и времени отображается, как показано ниже:
ЭЛЕМЕНТ HTML
Отображает HTMLElement
значение его Caption
свойства в ячейке таблицы. Выбранный Whe, Url
назначенный элементу UIWebView
, загружается в элемент управления, как показано ниже:
Элемент сообщения
Загрузить дополнительный элемент
Используйте этот элемент, чтобы разрешить пользователям загружать больше элементов в списке. Вы можете настроить обычные и загружаемые субтитры, а также цвет шрифта и текста.
Индикатор UIActivity
начинает анимироваться, а подпись загрузки отображается при касании ячейки пользователем, а затем NSAction
передается в конструктор. После завершения UIActivity
кода NSAction
индикатор перестает анимироваться, а обычный заголовок отображается снова.
Элемент UIView
Кроме того, любое пользовательское UIView
можно отобразить с помощью .UIViewElement
Элемент ,нарисованный владельцем
Этот элемент должен быть подклассом, так как это абстрактный класс. Необходимо переопределить 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);
Дополнительные сведения об использовании JSON с MT. D, см. руководство по пошаговому руководству по элементу JSON.
Другие возможности
Поддержка обновления по запросу
Вытягивание к обновлению — это визуальный эффект, первоначально найденный в приложении Tweetie2, который стал популярным эффектом среди многих приложений.
Чтобы добавить поддержку автоматического извлечения в диалоговые окна, необходимо выполнить только две действия: подключить обработчик событий, чтобы получать уведомления, когда пользователь извлекает данные и уведомляет DialogViewController
о том, когда данные были загружены, чтобы вернуться к состоянию по умолчанию.
Подключение уведомления простое; Просто подключитесь к событию RefreshRequested
в DialogViewController
следующем:
dvc.RefreshRequested += OnUserRequestedRefresh;
Затем в методе OnUserRequestedRefresh
вы будете очереди загрузки некоторых данных, запрашивать некоторые данные из сети или спинировать поток для вычисления данных. После загрузки данных необходимо уведомить DialogViewController
о том, что новые данные включено, а также восстановить представление до его состояния по умолчанию, выполнив вызов:ReloadComplete
dvc.ReloadComplete ();
Поддержка поиска
Чтобы поддержать поиск, задайте свойство в вашей учетной EnableSearch
записи DialogViewController
. Вы также можете задать SearchPlaceholder
свойство, которое будет использоваться в качестве подложки в строке поиска.
Поиск изменит содержимое представления в качестве типов пользователей. Он выполняет поиск видимых полей и показывает их пользователю. Предоставляет DialogViewController
три метода для программного инициирования, завершения или активации новой операции фильтра в результатах. Ниже перечислены следующие методы.
StartSearch
FinishSearch
PerformFilter
Система расширяема, поэтому вы можете изменить это поведение, если вы хотите.
Загрузка фонового изображения
MonoTouch.Dialog включает загрузчик изображений приложения TweetStation . Этот загрузчик изображений можно использовать для загрузки изображений в фоновом режиме, поддерживает кэширование и может уведомлять код о загрузке образа.
Он также ограничивает количество исходящих сетевых подключений.
Загрузчик изображений реализуется в ImageLoader
классе, все, что необходимо сделать, — вызвать DefaultRequestImage
метод, необходимо указать универсальный код ресурса (URI) для изображения, который требуется загрузить, а также экземпляр IImageUpdated
интерфейса, который будет вызываться при загрузке образа.
Например, следующий код загружает изображение из URL-адреса в 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 предоставляет метод очистки, который можно вызвать, когда требуется освободить все образы, которые в настоящее время кэшируются в памяти. Текущий код содержит кэш для 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
Создание пользовательских элементов
Вы можете создать собственный элемент, наследуя от существующего элемента или из корневого элемента класса.
Чтобы создать собственный элемент, необходимо переопределить следующие методы:
// 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);
Если вы планируете реализовать GetCell
метод путем вызова base.GetCell(tv)
и настройки возвращаемой ячейки, необходимо также переопределить CellKey
свойство, чтобы вернуть ключ, который будет уникальным для элемента, как показано ниже.
static NSString MyKey = new NSString ("MyKey");
protected override NSString CellKey {
get {
return MyKey;
}
}
Это работает для большинства элементов, но не для StringElement
StyledStringElement
тех, кто использует собственный набор ключей для различных сценариев отрисовки. Необходимо реплицировать код в этих классах.
DialogViewControllers (DVCS)
И отражение, и API элементов используют одинаковые DialogViewController
. Иногда вы хотите настроить внешний вид представления или вы можете использовать некоторые функции UITableViewController
, которые выходят за рамки базового создания пользовательских интерфейсов.
Это 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
методов. Например, TwitterStation использует это для отслеживания, когда пользователь прокрутился в верхнюю часть и обновляет соответственно количество непрочитанных твитов.
Проверка
Элементы не предоставляют проверку как модели, которые хорошо подходят для веб-страниц и классических приложений, не сопоставляются непосредственно с моделью взаимодействия iPhone.
Если вы хотите выполнить проверку данных, это необходимо сделать, когда пользователь активирует действие с введенными данными. Например, кнопка "Готово " или "Далее " на верхней панели инструментов или некоторые, StringElement
используемые в качестве кнопки для перехода к следующему этапу.
Именно здесь вы будете выполнять базовую проверку входных данных и, возможно, более сложную проверку, например проверку допустимости сочетания пользователей и паролей с сервером.
Как вы уведомляете пользователя об ошибке, относящееся к приложению. Вы можете всплыть UIAlertView
или показать подсказку.
Итоги
В этой статье описано много сведений о MonoTouch.Dialog. Он обсудил основы того, как MT. D работает и охватывает различные компоненты, составляющие MT.D. Он также показал широкий массив элементов и настроек таблиц, поддерживаемых MT. D и обсудил, как MT. D можно расширить с помощью пользовательских элементов. Кроме того, он объяснил поддержку JSON в MT. D, который позволяет динамически создавать элементы из JSON.
Связанные ссылки
- Пошаговое руководство. Создание приложения с помощью API элементов
- Пошаговое руководство. Создание приложения с помощью API отражения
- Пошаговое руководство. Использование элемента JSON для создания пользовательского интерфейса
- Разметка MonoTouch.Dialog JSON
- Диалоговое окно MonoTouch на Github
- Справочник по классу UITableViewController
- Справочник по классу UINavigationController