Работа с полями текста и поиска tvOS в Xamarin

При необходимости приложение Xamarin.tvOS может запрашивать небольшие фрагменты текста от пользователя (например, идентификаторы пользователей и пароли), используя текстовое поле и экранную клавиатуру:

Пример поля поиска

При необходимости можно предоставить возможность поиска ключевое слово содержимого приложения с помощью поля поиска:

Примеры результатов поиска

В этом документе рассматриваются сведения о работе с полями текста и поиска в приложении Xamarin.tvOS.

Сведения о полях текста и поиска

Как указано выше, при необходимости ваш Xamarin.tvOS может представить один или несколько текстовых полей для сбора небольших объемов текста от пользователя с помощью экранной клавиатуры (или необязательной клавиатуры Bluetooth в зависимости от установленной версии tvOS).

Кроме того, если приложение предоставляет пользователю большое количество содержимого (например, музыку, фильмы или коллекцию рисунков), может потребоваться включить поле поиска, позволяющее пользователю ввести небольшой объем текста для фильтрации списка доступных элементов.

Текстовые поля

В tvOS текстовое поле представлено как поле с фиксированной высотой, закругляемое угловое поле, которое откроет экранную клавиатуру, когда пользователь щелкает его:

Текстовые поля в tvOS

Когда пользователь перемещает фокус на заданное текстовое поле, он будет увеличиваться и отображать глубокую тень. Это необходимо учитывать при проектировании пользовательского интерфейса, так как текстовые поля могут перекрывать другие элементы пользовательского интерфейса при фокусе.

Apple предлагает следующие предложения по работе с текстовыми полями:

  • Используйте запись текста в разреженном режиме. Из-за характера экранной клавиатуры ввод длинных разделов текста или заполнение нескольких текстовых полей неуловим для пользователя. Лучше всего ограничить объем записи текста с помощью списков выделения или кнопок.
  • Используйте подсказки для обмена данными. Текстовое поле может отображать заполнитель "подсказки" при пустом значении. Если применимо, используйте указания, чтобы описать назначение текстового поля вместо отдельной метки.
  • Выберите подходящий тип клавиатуры по умолчанию — tvOS предоставляет несколько различных встроенных типов клавиатуры, которые можно указать для текстового поля. Например, клавиатура адреса электронной почты может упростить запись, позволяя пользователю выбирать из списка недавно введенных адресов.
  • При необходимости используйте безопасные текстовые поля — безопасное текстовое поле представляет символы, введенные как точки (вместо реальных букв). Всегда используйте безопасное текстовое поле при сборе конфиденциальных данных, таких как пароли.

Клавиатуры

Когда пользователь щелкает текстовое поле в пользовательском интерфейсе, отображается линейная клавиатура на экране. Пользователь использует Сенсорный surface siri Remote для выбора отдельных букв на клавиатуре и ввода запрошенных сведений:

Удаленная клавиатура Siri

Если в текущем представлении существует несколько текстовых полей, кнопка "Далее" будет автоматически отображаться, чтобы перейти к следующему текстовому полю. Кнопка "Готово " будет отображаться для последнего текстового поля, которое завершит запись текста и вернет пользователя на предыдущий экран.

В любой момент пользователь также может нажать кнопку меню в записи удаленного текста Siri и снова вернуться на предыдущий экран.

Apple предлагает следующие предложения по работе с клавиатурами на экране:

  • Выберите подходящий тип клавиатуры по умолчанию — tvOS предоставляет несколько различных встроенных типов клавиатуры, которые можно указать для текстового поля. Например, клавиатура адреса электронной почты может упростить запись, позволяя пользователю выбирать из списка недавно введенных адресов.
  • При необходимости используйте представления аксессуаров клавиатуры. Помимо стандартных сведений, которые всегда отображаются, дополнительные представления аксессуаров (например, изображения или метки) можно добавить на экранную клавиатуру, чтобы уточнить назначение записи текста или помочь пользователю в вводе необходимых сведений.

Дополнительные сведения о работе с экранной клавиатурой см. в документации по iOS по управлению клавиатурой, пользовательским представлениям для ввода данных и программирования текста в документации по iOS.

Поле поиска представляет специализированный экран, предоставляющий текстовое поле и экранную клавиатуру, которая позволяет пользователю фильтровать коллекцию элементов, отображаемых под клавиатурой:

Примеры результатов поиска

Когда пользователь вводит буквы в поле поиска, приведенные ниже результаты автоматически отражают результаты поиска. В любое время пользователь может переместить фокус на результаты и выбрать один из представленных элементов.

Apple предлагает следующие предложения по работе с полями поиска:

  • Укажите последние поисковые запросы . Так как ввод текста с помощью Siri Remote может быть емким, и пользователи, как правило, повторяют поисковые запросы, рассмотрите возможность добавления раздела "Последние результаты поиска" перед текущими результатами в области клавиатуры.
  • По возможности ограничить количество результатов . Так как большой список элементов может быть сложным для пользователя для синтаксического анализа и навигации, рассмотрите возможность ограничения количества возвращаемых результатов.
  • При необходимости укажите фильтры результатов поиска. Если содержимое, предоставленное приложением, предоставляется, попробуйте добавить область полосы, чтобы разрешить пользователю дополнительно фильтровать возвращаемые результаты поиска.

Дополнительные сведения см. в справочнике по классу UISearchController Apple.

Работа с текстовыми полями

Самый простой способ работы с текстовыми полями в приложении Xamarin.tvOS — добавить их в дизайн пользовательского интерфейса с помощью конструктора iOS.

Выполните следующие действия.

  1. На панели решений дважды щелкните Main.storyboard файл, чтобы открыть его для редактирования.

  2. Перетащите одну или несколько текстовых полей в область конструктора в представление:

    Текстовое поле

  3. Выберите текстовые поля и присвойте каждому уникальному имени на вкладке "Мини-приложение" панели свойств:

    Вкладка

  4. В разделе "Текстовое поле" можно определить такие элементы, как указание заполнителя и значение по умолчанию:

    Раздел

  5. Прокрутите вниз, чтобы определить такие свойства, как проверка орфографии, прописная буква и тип клавиатуры по умолчанию:

    Проверка орфографии, прописная буква и тип клавиатуры по умолчанию

  6. Сохраните изменения в раскадровке.

В коде можно получить или задать значение текстового поля с помощью его Text свойства:

Console.WriteLine ("User ID {0} and Password {1}", UserId.Text, Password.Text);

При необходимости можно использовать Started события и Ended события текстового поля для реагирования на запись текста, начиная и заканчивая.

Работа с полями поиска

Самый простой способ работы с полями поиска в приложении Xamarin.tvOS — добавить их в дизайн пользовательского интерфейса с помощью конструктора интерфейсов.

Выполните следующие действия.

  1. На панели решений дважды щелкните Main.storyboard файл, чтобы открыть его для редактирования.

  2. Перетащите новый контроллер представления коллекции в раскадровку, чтобы представить результаты поиска пользователя:

    Контроллер представления коллекции

  3. На вкладке "Мини-приложение" панели свойств используйте SearchResultsViewController класси SearchResultsидентификатор раскадровки:

    Вкладка

  4. Выберите прототип ячейки на поверхности конструктора.

  5. На вкладке "Мини-приложение" Обозреватель свойств используйте SearchResultCell для класса и ImageCell идентификатора:

    Вкладка

  6. Макет макета прототипа ячейки и предоставление каждого элемента с уникальным именем на вкладке "Мини-приложение" Обозреватель свойств:

    Макет макета прототипа ячейки

  7. Сохраните изменения в раскадровке.

Предоставление модели данных

Затем необходимо предоставить класс, который будет выступать в качестве модели данных для результатов, которые пользователь будет искать. В Обозреватель решений щелкните правой кнопкой мыши имя проекта и выберите "Добавить>новый файл" ...>Общий>пустой класс и укажите имя:

Выберите пустой класс и укажите имя

Например, приложение, которое позволяет пользователю искать коллекцию изображений по заголовку и ключевому слову, может выглядеть следующим образом:

using System;
using Foundation;

namespace tvText
{
    public class PictureInformation : NSObject
    {
        #region Computed Properties
        public string Title { get; set;}
        public string ImageName { get; set;}
        public string Keywords { get; set;}
        #endregion

        #region Constructors
        public PictureInformation (string title, string imageName, string keywords)
        {
            // Initialize
            this.Title = title;
            this.ImageName = imageName;
            this.Keywords = keywords;
        }
        #endregion
    }
}

Ячейка представления коллекции

На месте модели данных измените ячейку прототипа (SearchResultViewCell.cs) и сделайте ее выглядят следующим образом:

using Foundation;
using System;
using UIKit;

namespace tvText
{
    public partial class SearchResultViewCell : UICollectionViewCell
    {
        #region Private Variables
        private PictureInformation _pictureInfo = null;
        #endregion

        #region Computed Properties
        public PictureInformation PictureInfo {
            get { return _pictureInfo; }
            set {
                _pictureInfo = value;
                UpdateUI ();
            }
        }
        #endregion

        #region Constructors
        public SearchResultViewCell (IntPtr handle) : base (handle)
        {
            // Initialize
            UpdateUI ();
        }
        #endregion

        #region Private Methods
        private void UpdateUI ()
        {
            // Anything to process?
            if (PictureInfo == null) return;

            try {
                Picture.Image = UIImage.FromBundle (PictureInfo.ImageName);
                Picture.AdjustsImageWhenAncestorFocused = true;
                Title.Text = PictureInfo.Title;
                TextColor = UIColor.LightGray;
            } catch {
                // Ignore errors if view isn't fully loaded
            }
        }
        #endregion
    }

}

Метод UpdateUI будет использоваться для отображения отдельных полей элементов PictureInformation ( PictureInfo свойство) в именованных элементах пользовательского интерфейса при каждом обновлении свойства. Например, изображение и заголовок, связанные с рисунком.

Контроллер представления коллекции

Затем измените контроллер представления коллекции результатов поиска (SearchResultsViewController.cs) и сделайте его следующим образом:

using Foundation;
using System;
using UIKit;
using System.Collections.Generic;

namespace tvText
{
    public partial class SearchResultsViewController : UICollectionViewController , IUISearchResultsUpdating
    {
        #region Constants
        public const string CellID = "ImageCell";
        #endregion

        #region Private Variables
        private string _searchFilter = "";
        #endregion

        #region Computed Properties
        public List<PictureInformation> AllPictures { get; set;}
        public List<PictureInformation> FoundPictures { get; set; }
        public string SearchFilter {
            get { return _searchFilter; }
            set {
                _searchFilter = value.ToLower();
                FindPictures ();
                CollectionView?.ReloadData ();
            }
        }
        #endregion

        #region Constructors
        public SearchResultsViewController (IntPtr handle) : base (handle)
        {
            // Initialize
            this.AllPictures = new List<PictureInformation> ();
            this.FoundPictures = new List<PictureInformation> ();
            PopulatePictures ();
            FindPictures ();

        }
        #endregion

        #region Private Methods
        private void PopulatePictures ()
        {
            // Clear list
            AllPictures.Clear ();

            // Add images
            AllPictures.Add (new PictureInformation ("Antipasta Platter","Antipasta","cheese,grapes,tomato,coffee,meat,plate"));
            AllPictures.Add (new PictureInformation ("Cheese Plate", "CheesePlate", "cheese,plate,bread"));
            AllPictures.Add (new PictureInformation ("Coffee House", "CoffeeHouse", "coffee,people,menu,restaurant,cafe"));
            AllPictures.Add (new PictureInformation ("Computer and Expresso", "ComputerExpresso", "computer,coffee,expresso,phone,notebook"));
            AllPictures.Add (new PictureInformation ("Hamburger", "Hamburger", "meat,bread,cheese,tomato,pickle,lettus"));
            AllPictures.Add (new PictureInformation ("Lasagna Dinner", "Lasagna", "salad,bread,plate,lasagna,pasta"));
            AllPictures.Add (new PictureInformation ("Expresso Meeting", "PeopleExpresso", "people,bag,phone,expresso,coffee,table,tablet,notebook"));
            AllPictures.Add (new PictureInformation ("Soup and Sandwich", "SoupAndSandwich", "soup,sandwich,bread,meat,plate,tomato,lettus,egg"));
            AllPictures.Add (new PictureInformation ("Morning Coffee", "TabletCoffee", "tablet,person,man,coffee,magazine,table"));
            AllPictures.Add (new PictureInformation ("Evening Coffee", "TabletMagCoffee", "tablet,magazine,coffee,table"));
        }

        private void FindPictures ()
        {
            // Clear list
            FoundPictures.Clear ();

            // Scan each picture for a match
            foreach (PictureInformation picture in AllPictures) {
                if (SearchFilter == "") {
                    // If no search term, everything matches
                    FoundPictures.Add (picture);
                } else if (picture.Title.Contains (SearchFilter) || picture.Keywords.Contains (SearchFilter)) {
                    // If the search term is in the title or keywords, we've found a match
                    FoundPictures.Add (picture);
                }
            }
        }
        #endregion

        #region Override Methods
        public override nint NumberOfSections (UICollectionView collectionView)
        {
            // Only one section in this collection
            return 1;
        }

        public override nint GetItemsCount (UICollectionView collectionView, nint section)
        {
            // Return the number of matching pictures
            return FoundPictures.Count;
        }

        public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
        {
            // Get a new cell and return it
            var cell = collectionView.DequeueReusableCell (CellID, indexPath);
            return (UICollectionViewCell)cell;
        }

        public override void WillDisplayCell (UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
        {
            // Grab the cell
            var currentCell = cell as SearchResultViewCell;
            if (currentCell == null)
                throw new Exception ("Expected to display a `SearchResultViewCell`.");

            // Display the current picture info in the cell
            var item = FoundPictures [indexPath.Row];
            currentCell.PictureInfo = item;
        }

        public override void ItemSelected (UICollectionView collectionView, NSIndexPath indexPath)
        {
            // If this Search Controller was presented as a modal view, close
            // it before continuing
            // DismissViewController (true, null);

            // Grab the picture being selected and report it
            var picture = FoundPictures [indexPath.Row];
            Console.WriteLine ("Selected: {0}", picture.Title);
        }

        public void UpdateSearchResultsForSearchController (UISearchController searchController)
        {
            // Save the search filter and update the Collection View
            SearchFilter = searchController.SearchBar.Text ?? string.Empty;
        }

        public override void DidUpdateFocus (UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
        {
            var previousItem = context.PreviouslyFocusedView as SearchResultViewCell;
            if (previousItem != null) {
                UIView.Animate (0.2, () => {
                    previousItem.TextColor = UIColor.LightGray;
                });
            }

            var nextItem = context.NextFocusedView as SearchResultViewCell;
            if (nextItem != null) {
                UIView.Animate (0.2, () => {
                    nextItem.TextColor = UIColor.Black;
                });
            }
        }
        #endregion
    }
}

Во-первых, IUISearchResultsUpdating интерфейс добавляется в класс для обработки фильтра контроллера поиска, обновляемого пользователем:

public partial class SearchResultsViewController : UICollectionViewController , IUISearchResultsUpdating

Константа также определяется для указания идентификатора ячейки прототипа (который соответствует идентификатору, определенному в конструкторе интерфейсов выше), который будет использоваться позже, когда контроллер сбора запрашивает новую ячейку:

public const string CellID = "ImageCell";

служба хранилища создается для полного списка элементов поиска, термина фильтра поиска и списка элементов, соответствующих этим термину:

private string _searchFilter = "";
...

public List<PictureInformation> AllPictures { get; set;}
public List<PictureInformation> FoundPictures { get; set; }
public string SearchFilter {
    get { return _searchFilter; }
    set {
        _searchFilter = value.ToLower();
        FindPictures ();
        CollectionView?.ReloadData ();
    }
}

SearchFilter После изменения список соответствующих элементов обновляется, а содержимое представления коллекции перезагрузится. Подпрограмма FindPictures отвечает за поиск элементов, соответствующих новому термину поиска:

private void FindPictures ()
{
    // Clear list
    FoundPictures.Clear ();

    // Scan each picture for a match
    foreach (PictureInformation picture in AllPictures) {
        if (SearchFilter == "") {
            // If no search term, everything matches
            FoundPictures.Add (picture);
        } else if (picture.Title.Contains (SearchFilter) || picture.Keywords.Contains (SearchFilter)) {
            // If the search term is in the title or keywords, we've found a match
            FoundPictures.Add (picture);
        }
    }
}

Значение SearchFilter будет обновлено (которое будет обновлять представление коллекции результатов) при изменении фильтра в контроллере поиска:

public void UpdateSearchResultsForSearchController (UISearchController searchController)
{
    // Save the search filter and update the Collection View
    SearchFilter = searchController.SearchBar.Text ?? string.Empty;
}

Метод PopulatePictures изначально заполняет коллекцию доступных элементов:

private void PopulatePictures ()
{
    // Clear list
    AllPictures.Clear ();

    // Add images
    AllPictures.Add (new PictureInformation ("Antipasta Platter","Antipasta","cheese,grapes,tomato,coffee,meat,plate"));
    ...
}

В этом примере все примеры данных создаются в памяти при загрузке контроллера представления коллекции. В реальном приложении эти данные, вероятно, будут считываться из базы данных или веб-службы, и только по мере необходимости, чтобы не перерасходить ограниченную память Apple TV.

GetItemsCount Методы NumberOfSections предоставляют количество сопоставленных элементов:

public override nint NumberOfSections (UICollectionView collectionView)
{
    // Only one section in this collection
    return 1;
}

public override nint GetItemsCount (UICollectionView collectionView, nint section)
{
    // Return the number of matching pictures
    return FoundPictures.Count;
}

Метод GetCell возвращает новую ячейку прототипа (на основе определенного CellID выше в раскадровки) для каждого элемента в представлении коллекции:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
    // Get a new cell and return it
    var cell = collectionView.DequeueReusableCell (CellID, indexPath);
    return (UICollectionViewCell)cell;
}

Метод WillDisplayCell вызывается до отображаемой ячейки, чтобы ее можно было настроить:

public override void WillDisplayCell (UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
{
    // Grab the cell
    var currentCell = cell as SearchResultViewCell;
    if (currentCell == null)
        throw new Exception ("Expected to display a `SearchResultViewCell`.");

    // Display the current picture info in the cell
    var item = FoundPictures [indexPath.Row];
    currentCell.PictureInfo = item;
}

Этот DidUpdateFocus метод предоставляет визуальный отзыв пользователю по мере выделения элементов в представлении коллекции результатов:

public override void DidUpdateFocus (UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
    var previousItem = context.PreviouslyFocusedView as SearchResultViewCell;
    if (previousItem != null) {
        UIView.Animate (0.2, () => {
            previousItem.TextColor = UIColor.LightGray;
        });
    }

    var nextItem = context.NextFocusedView as SearchResultViewCell;
    if (nextItem != null) {
        UIView.Animate (0.2, () => {
            nextItem.TextColor = UIColor.Black;
        });
    }
}

Наконец, ItemSelected метод обрабатывает пользователя, выбрав элемент (щелкнув Touch Surface с помощью Siri Remote) в представлении коллекции результатов:

public override void ItemSelected (UICollectionView collectionView, NSIndexPath indexPath)
{
    // If this Search Controller was presented as a modal view, close
    // it before continuing
    // DismissViewController (true, null);

    // Grab the picture being selected and report it
    var picture = FoundPictures [indexPath.Row];
    Console.WriteLine ("Selected: {0}", picture.Title);
}

Если поле поиска было представлено в виде модального диалогового окна (в верхней части вызываемого представления), используйте DismissViewController метод, чтобы закрыть представление поиска, когда пользователь выбирает элемент. В этом примере поле поиска отображается как содержимое вкладки "Представление вкладок", поэтому здесь не закрывается.

Дополнительные сведения о представлениях коллекции см . в документации по работе с представлениями коллекции.

Представление поля поиска

Существует два основных способа представления поля поиска (и связанных с ним экранных клавиатур и результатов поиска) пользователю в tvOS:

  • Модальное диалоговое окно — поле поиска может быть представлено в текущем режиме представления и просмотра в виде модального представления полноэкранного диалогового окна. Обычно это делается в ответ на нажатие кнопки или другого элемента пользовательского интерфейса. Диалоговое окно закрывается, когда пользователь выбирает элемент из результатов поиска.
  • Содержимое представления. Поле поиска является прямой частью данного представления. Например, как содержимое вкладки поиска в контроллере представления вкладок.

Например, список изображений, доступных для поиска выше, поле поиска представлено как "Содержимое представления" на вкладке "Поиск", а контроллер представления вкладки поиска выглядит следующим образом:

using System;
using UIKit;

namespace tvText
{
    public partial class SecondViewController : UIViewController
    {
        #region Constants
        public const string SearchResultsID = "SearchResults";
        #endregion

        #region Computed Properties
        public SearchResultsViewController ResultsController { get; set;}
        #endregion

        #region Constructors
        public SecondViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Private Methods
        public void ShowSearchController ()
        {
            // Build an instance of the Search Results View Controller from the Storyboard
            ResultsController = Storyboard.InstantiateViewController (SearchResultsID) as SearchResultsViewController;
            if (ResultsController == null)
                throw new Exception ("Unable to instantiate a SearchResultsViewController.");

            // Create an initialize a new search controller
            var searchController = new UISearchController (ResultsController) {
                SearchResultsUpdater = ResultsController,
                HidesNavigationBarDuringPresentation = false
            };

            // Set any required search parameters
            searchController.SearchBar.Placeholder = "Enter keyword (e.g. coffee)";

            // The Search Results View Controller can be presented as a modal view
            // PresentViewController (searchController, true, null);

            // Or in the case of this sample, the Search View Controller is being
            // presented as the contents of the Search Tab directly. Use either one
            // or the other method to display the Search Controller (not both).
            var container = new UISearchContainerViewController (searchController);
            var navController = new UINavigationController (container);
            AddChildViewController (navController);
            View.Add (navController.View);
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // If the Search Controller is being displayed as the content
            // of the search tab, include it here.
            ShowSearchController ();
        }

        public override void ViewDidAppear (bool animated)
        {
            base.ViewDidAppear (animated);

            // If the Search Controller is being presented as a modal view,
            // call it here to display it over the contents of the Search
            // tab.
            // ShowSearchController ();
        }
        #endregion
    }
}

Во-первых, константа определяется, которая соответствует идентификатору раскадровки, назначенному контроллеру представления коллекции результатов поиска в конструкторе интерфейсов:

public const string SearchResultsID = "SearchResults";

ShowSearchController Затем метод создает новый контроллер коллекции представлений поиска и отображает его необходимо:

public void ShowSearchController ()
{
    // Build an instance of the Search Results View Controller from the Storyboard
    ResultsController = Storyboard.InstantiateViewController (SearchResultsID) as SearchResultsViewController;
    if (ResultsController == null)
        throw new Exception ("Unable to instantiate a SearchResultsViewController.");

    // Create an initialize a new search controller
    var searchController = new UISearchController (ResultsController) {
        SearchResultsUpdater = ResultsController,
        HidesNavigationBarDuringPresentation = false
    };

    // Set any required search parameters
    searchController.SearchBar.Placeholder = "Enter keyword (e.g. coffee)";

    // The Search Results View Controller can be presented as a modal view
    // PresentViewController (searchController, true, null);

    // Or in the case of this sample, the Search View Controller is being
    // presented as the contents of the Search Tab directly. Use either one
    // or the other method to display the Search Controller (not both).
    var container = new UISearchContainerViewController (searchController);
    var navController = new UINavigationController (container);
    AddChildViewController (navController);
    View.Add (navController.View);
}

В приведенном выше методе после SearchResultsViewController создания экземпляра из раскадровки создается новое UISearchController , чтобы представить поле поиска и экранную клавиатуру пользователю. Коллекция результатов поиска (как определено этим параметром SearchResultsViewController) будет отображаться на этой клавиатуре.

SearchBar Затем настраивается информация, например указание заполнителя. Это предоставляет пользователю сведения о типе предварительно сформированного поиска.

Затем поле поиска будет представлено пользователю одним из двух способов:

  • Модальное диалоговое окноPresentViewController вызывается метод для представления поиска по существующему представлению в полноэкранном режиме.
  • Содержимое представления — создается для UISearchContainerViewController хранения контроллера поиска. Создается UINavigationController для хранения контейнера поиска, затем контроллер навигации добавляется в контроллер AddChildViewController (navController)представления, а представление представлено View.Add (navController.View).

Наконец, и снова на основе типа ViewDidLoadViewDidAppear презентации или метода вызовет ShowSearchController метод, чтобы представить поиск пользователю:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // If the Search Controller is being displayed as the content
    // of the search tab, include it here.
    ShowSearchController ();
}

public override void ViewDidAppear (bool animated)
{
    base.ViewDidAppear (animated);

    // If the Search Controller is being presented as a modal view,
    // call it here to display it over the contents of the Search
    // tab.
    // ShowSearchController ();
}

При запуске приложения и вкладке поиска, выбранной пользователем, полный нефильтрованный список элементов будет представлен пользователю:

Результаты поиска по умолчанию

Когда пользователь начинает вводить поисковый термин, список результатов будет отфильтрован этим термином и обновляется автоматически:

Отфильтрованные результаты поиска

В любое время пользователь может переключить фокус на элемент в результатах поиска и щелкнуть сенсорное устройство Siri Remote, чтобы выбрать его.

Итоги

В этой статье рассматривается проектирование и работа с полями текста и поиска в приложении Xamarin.tvOS. В нем показано, как создать содержимое коллекции текста и поиска в конструкторе интерфейсов, и он показал два разных способа представления поля поиска пользователю в tvOS.