Поделиться через


Сводка по главе 24. Перемещение по страницам

Примечание.

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

Многие приложения состоят из нескольких страниц, по которым переходит пользователь. У приложения всегда есть главная или домашняя страница, с которой пользователь переходит на другие страницы, которые помещаются в стек для переходов назад. Дополнительные параметры навигации рассматриваются в главе 25. Разновидности страниц.

VisualElement определяет свойство Navigation с типом INavigation, который включает следующие два метода для перехода на новую страницу:

Оба метода принимают в качестве аргумента экземпляр Page и возвращают объект Task. Следующие два метода возвращают пользователя на предыдущую страницу.

Если в пользовательском интерфейсе есть собственная кнопка Назад (например, на смартфонах Android и Windows), вызывать эти методы в приложении нет необходимости.

Хотя эти методы доступны в любом классе VisualElement, обычно они вызываются из свойства Navigation текущего экземпляра Page.

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

Пример ModelessAndModal позволяет изучить разницу между модальными и немодальными страницами. Любое приложение со страничной системой навигации должно передавать свою домашнюю страницу конструктору NavigationPage, обычно в классе App программы. Это удобно хотя бы тем, что теперь не нужно задавать Padding на странице для iOS.

Вы обнаружите, что для немодальных страниц отображается свойство страницы Title. Платформы iOS, Android и Windows для планшетов и настольных компьютеров предоставляют элемент пользовательского интерфейса для возврата на предыдущую страницу. Кроме того, на устройствах Android и Windows Phone для возврата есть стандартная кнопка Назад.

Для модальных страниц страница Title не отображается, и элемент пользовательского интерфейса для возврата на предыдущую страницу отсутствует. На смартфонах Android и Windows вы можете использовать стандартную кнопку Назад, чтобы вернуться на предыдущую страницу, но для других платформ модальная страница должна предоставить собственный механизм возврата.

Анимация переходов по страницам

Альтернативные версии методов навигации предоставляются с дополнительным логическим аргументом, которому вы присваиваете значение true, если хотите применить анимацию к переходу между страницами:

Однако стандартные методы навигации по страницам включают анимацию по умолчанию, поэтому они полезны только для перехода на определенную страницу при запуске (как описано в конце этой главы) или при предоставлении собственной анимации входа (как описано в главе 22). Анимация).

Визуальные и функциональные варианты

NavigationPage содержит два свойства, которые можно задать при создании экземпляра класса в методе App:

Кроме того, NavigationPage включает четыре присоединенных привязываемых свойства, которые влияют на определенную страницу, для которой они заданы:

Изучение механизма работы

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

При переходе с одной страницы на другую первая страница обычно получает вызов метода OnDisappearing, а вторая — метода OnAppearing. Аналогичным образом, при возврате с одной страницы на другую первая страница обычно получает вызов метода OnDisappearing, а вторая — метода OnAppearing. Порядок этих вызовов и время завершения методов, которые вызвали эту навигацию, зависят от платформы. Слово "обычно" в двух предшествующих заявлениях появилось из-за навигации по модальным страницам в Android, где эти методы не вызываются.

Кроме того, вызов методов OnAppearing и OnDisappearing не всегда связан с навигацией между страницами.

Интерфейс INavigation содержит два свойства коллекции, которые позволяют изучать стек навигации:

  • NavigationStack с типом IReadOnlyList<Page> для немодального стека;
  • ModalStack с типом IReadOnlyList<Page> для модального стека.

Самый безопасный вариант доступа к стекам — из свойства Navigation в классе NavigationPage (в котором должно находиться свойство MainPage класса App). Изучение стеков считается безопасным только после завершения работы асинхронных методов навигации между страницами. Свойство CurrentPage класса NavigationPage не соответствует текущей странице, если текущая страница является модальной. В такой ситуации это свойство соответствует последней немодальной странице.

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

  • с немодальной страницы можно переходить на другую немодальную или модальную страницу;
  • с модальной страницы можно переходить только на другую модальную страницу.

Принудительное применение модальности

Приложение использует модальную страницу, когда ему требуется некоторая информация от пользователя. У пользователя не должно быть возможности вернуться на предыдущую страницу, пока эта информация не будет предоставлена. На iOS очень легко создать кнопку Назад и включать ее только после завершения работы на текущей странице. Но на смартфонах Android и Windows приложение должно переопределить метод OnBackButtonPressed и возвращать true, если программа самостоятельно обработала нажатие кнопки Назад, как показано в примере ModalEnforcement.

Пример MvvmEnforcement демонстрирует работу этого механизма для сценария MVVM.

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

Создание меню навигации

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

Три снимка экрана с представлением типа коллекции

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

Управление стеком навигации

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

Динамическое создание страниц

Пример BuildAPage демонстрирует создание страницы в среде выполнения в ответ на ввод данных пользователем.

Шаблоны передачи данных

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

Аргументы конструктора

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

Свойства и вызовы методов

Остальные примеры передачи данных посвящены изучению проблемы с передачей данных между страницами в тех случаях, когда пользователь переходит с одной страницы на другую и обратно. В этих обсуждениях страница home выполняет переход на страницу info и должна передавать инициализированную информацию на страницу info. Страница info получает дополнительную информацию от пользователя и передает эту информацию на страницу home.

Страница home может легко применить общие методы и свойства страницы info после того, как создаст ее экземпляр. Страница info также может применить общие методы и свойства страницы home, но здесь сложнее выбрать правильный момент. Пример DateTransfer1 выполняет эти действия в переопределении OnDisappearing. Это плохо тем, что страница info должна иметь сведения о типе страницы home.

MessagingCenter

Класс Xamarin.FormsMessagingCenter предоставляет еще один способ взаимодействия между двумя страницами. Сообщения идентифицируются по текстовой строке и могут дополняться объектами.

Программа, которая намерена получать сообщения определенного типа, должна подписаться на них с помощью MessagingCenter.Subscribe и указать функцию обратного вызова. Позже она может отменить подписку, вызвав MessagingCenter.Unsubscribe. Функция обратного вызова будет получать все сообщения, отправленные из указанного типа с указанным именем через метод Send.

Программа DateTransfer2 демонстрирует процесс передачи данных через центр обмена сообщениями, но и в этом сценарии страница info должна знать тип страницы home.

События

События уже давно считаются общепризнанным способом передачи информации от одного класса другому, не выясняя тип второго класса. В примере DateTransfer3 класс info определяет событие, которое срабатывает при наличии готовой информации. Однако, не существует удобного места, где страница info могла бы отсоединить обработчик событий.

Класс-посредник App

В примере DateTransfer4 демонстрируется, как страницы home и info используют свойства, которые определены в классе App. Это хорошее решение, но в следующем разделе есть вариант еще лучше.

Переход на ViewModel

Использование ViewModel для хранения информации позволяет страницам home и info совместно использовать один экземпляр класса information. Это показано в примере DateTransfer5.

Сохранение и восстановление состояния страницы

Класс-посредник App в архитектуре ViewModel идеально подходит для ситуаций, когда приложению нужно сохранять информацию при переходе программы в спящий режим при активной странице info. Пример DateTransfer6 демонстрирует такой сценарий.

Сохранение и восстановление стека навигации

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

В библиотеке Xamarin.FormsBook.Toolkit определен интерфейс с именем IPersistantPage, который классы могут реализовать для сохранения данных в словаре Properties и их восстановления из словаря.

Класс MultiPageRestorableApp в библиотеке Xamarin.FormsBook.Toolkit наследует от Application. Вы можете наследовать свой класс App от MultiPageRestorableApp и выполнять в нем действия по обслуживанию.

В примере StackRestoreDemo демонстрируется использование MultiPageRestorableApp.

Что-то похожее на настоящее приложение

Пример NoteTaker также использует MultiPageRestorableApp и позволяет вводить и редактировать заметки, которые сохраняются в словаре Properties.