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


Настройка ContentPage

ContentPage — это визуальный элемент, который отображает одно представление и занимает большую часть экрана. В этой статье показано, как создать пользовательский отрисовщик для страницы ContentPage, чтобы переопределять собственный способ отрисовки по умолчанию с помощью настройки в зависимости от платформы.

Каждый элемент управления Xamarin.Forms имеет сопутствующий отрисовщик для каждой платформы, который создает экземпляр собственного элемента управления. Когда ContentPage отображается в приложении Xamarin.Forms, на платформе iOS создается класс PageRenderer, который, в свою очередь, создает собственный элемент управления UIViewController. На платформе Android класс PageRenderer создает элемент управления ViewGroup. На универсальной платформе Windows (UWP) класс PageRenderer создает элемент управления FrameworkElement. Дополнительные сведения об отрисовщике и классах собственных элементов управления, с которыми сопоставляются элементы управления Xamarin.Forms, см. в статье Базовые классы и собственные элементы управления отрисовщика.

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

Связь между классом ContentPage и реализующими нативными элементами управления

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

  1. Создание страницы Xamarin.Forms.
  2. Использование страницы из Xamarin.Forms.
  3. Создание пользовательского отрисовщика для страницы на каждой платформе.

Мы рассмотрим каждый пункт по порядку, чтобы реализовать класс CameraPage с возможностями прямой видеотрансляции и фотографирования.

Создание страницы Xamarin.Forms

Неизмененный класс ContentPage можно добавить в общий проект Xamarin.Forms, как показано в следующем примере кода XAML.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomRenderer.CameraPage">
    <ContentPage.Content>
    </ContentPage.Content>
</ContentPage>

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

public partial class CameraPage : ContentPage
{
    public CameraPage ()
    {
        // A custom renderer is used to display the camera UI
        InitializeComponent ();
    }
}

В следующем примере кода показано создание страницы в C#.

public class CameraPageCS : ContentPage
{
    public CameraPageCS ()
    {
    }
}

Для прямой трансляции видео на каждой платформе будет использоваться экземпляр класса CameraPage. Настройка элемента управления будет осуществляться в пользовательском отрисовщике, поэтому дополнительная реализация в классе CameraPage не требуется.

Использование страницы Xamarin.Forms

В приложении Xamarin.Forms должен отображаться пустой класс CameraPage. Это происходит при нажатии кнопки в экземпляре MainPage, что, в свою очередь, приводит к выполнению метода OnTakePhotoButtonClicked, как показано в следующем примере кода.

async void OnTakePhotoButtonClicked (object sender, EventArgs e)
{
    await Navigation.PushAsync (new CameraPage ());
}

Код просто переходит к классу CameraPage, в котором пользовательские отрисовщики будут настраивать внешний вид страницы на каждой платформе.

Создание отрисовщика страницы на каждой платформе

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

  1. Создайте подкласс класса PageRenderer.
  2. Переопределение метода OnElementChanged, который отрисовывает собственную страницу, и написание логики для настройки страницы. Метод OnElementChanged вызывается при создании соответствующего элемента управления Xamarin.Forms.
  3. Добавление атрибута ExportRenderer в класс отрисовщика страницы, чтобы указать, что он будет использоваться для отрисовки страницы Xamarin.Forms. Этот атрибут используется для регистрации пользовательского отрисовщика в Xamarin.Forms.

Примечание.

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

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

Задачи проекта пользовательского отрисовщика CameraPage

Экземпляр CameraPage отрисовывается с помощью зависящих от платформы классов CameraPageRenderer, которые являются производными от класса PageRenderer данной платформы. В результате каждый экземпляр CameraPage отрисовывается в ходе прямой видеотрансляции, как показано на следующих снимках экрана.

CameraPage на каждой платформе

Класс PageRenderer предоставляет метод OnElementChanged, который вызывается при создании страницы Xamarin.Forms для отрисовки соответствующего собственного элемента управления. Этот метод принимает параметр ElementChangedEventArgs, содержащий свойства OldElement и NewElement. Эти свойства представляют элемент Xamarin.Forms, к которому был присоединен отрисовщик, и элемент Xamarin.Forms, к которому присоединен отрисовщик, соответственно. В примере приложения свойство OldElement будет иметь значение null, а свойство NewElement будет содержать ссылку на экземпляр CameraPage.

Настройка собственной страницы выполняется в переопределенной версии метода OnElementChanged в классе CameraPageRenderer. Ссылку на отрисовываемый экземпляр страницы Xamarin.Forms можно получить с помощью свойства Element.

Каждый класс пользовательского отрисовщика дополняется атрибутом ExportRenderer, который регистрирует отрисовщик в Xamarin.Forms. Атрибут принимает два параметра — имя типа отрисовываемой страницы Xamarin.Forms и имя типа пользовательского отрисовщика. Префикс assembly в атрибуте указывает, что атрибут применяется ко всей сборке.

В следующих разделах рассматривается реализация пользовательского отрисовщика CameraPageRenderer для каждой платформы.

Создание отрисовщика страницы на платформе iOS

В следующем примере кода показан отрисовщик страницы для платформы iOS.

[assembly:ExportRenderer (typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.iOS
{
    public class CameraPageRenderer : PageRenderer
    {
        ...

        protected override void OnElementChanged (VisualElementChangedEventArgs e)
        {
            base.OnElementChanged (e);

            if (e.OldElement != null || Element == null) {
                return;
            }

            try {
                SetupUserInterface ();
                SetupEventHandlers ();
                SetupLiveCameraStream ();
                AuthorizeCameraUse ();
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine (@"            ERROR: ", ex.Message);
            }
        }
        ...
    }
}

В результате вызова метода OnElementChanged базового класса создается элемент управления iOS UIViewController. Отрисовка трансляции видеопотока происходит только при условии, что отрисовщик еще не присоединен к существующему элементу Xamarin.Forms и существует экземпляр страницы, который отрисовывается пользовательским отрисовщиком.

Затем страница настраивается с помощью ряда методов, использующих API AVCapture для предоставления возможностей трансляции видеопотока и фотографирования.

Создание отрисовщика страницы на платформе Android

В следующем примере кода показан отрисовщик страницы для платформы Android.

[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.Droid
{
    public class CameraPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
    {
        ...
        public CameraPageRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                SetupUserInterface();
                SetupEventHandlers();
                AddView(view);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(@"            ERROR: ", ex.Message);
            }
        }
        ...
    }
}

В результате вызова метода OnElementChanged базового класса создается элемент управления ViewGroup Android, который является группой представлений. Отрисовка трансляции видеопотока происходит только при условии, что отрисовщик еще не присоединен к существующему элементу Xamarin.Forms и существует экземпляр страницы, который отрисовывается пользовательским отрисовщиком.

Затем страница настраивается путем вызова ряда методов, использующих API Camera для предоставления возможностей трансляции видеопотока и фотографирования. После этого вызывается метод AddView для добавления пользовательского интерфейса трансляции видеопотока в элемент управления ViewGroup. Обратите внимание, что для выполнения операций по измерению и действий с макетом на платформе Android также требуется переопределить метод OnLayout.

Создание отрисовщика страницы на платформе UWP

В следующем примере кода показан отрисовщик страницы для платформы UWP.

[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.UWP
{
    public class CameraPageRenderer : PageRenderer
    {
        ...
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                ...
                SetupUserInterface();
                SetupBasedOnStateAsync();

                this.Children.Add(page);
            }
            ...
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            page.Arrange(new Windows.Foundation.Rect(0, 0, finalSize.Width, finalSize.Height));
            return finalSize;
        }
        ...
    }
}

В результате вызова метода OnElementChanged базового класса создается элемент управления FrameworkElement, в котором отрисовывается страница. Отрисовка трансляции видеопотока происходит только при условии, что отрисовщик еще не присоединен к существующему элементу Xamarin.Forms и существует экземпляр страницы, который отрисовывается пользовательским отрисовщиком. Затем страница настраивается путем вызова ряда методов, использующих API MediaCapture для предоставления возможностей трансляции видеопотока и фотографирования. После этого настроенная страница добавляется в коллекцию Children для отображения.

При реализации пользовательского отрисовщика, который является производным от класса PageRenderer на платформе UWP, необходимо также реализовать метод ArrangeOverride для упорядочения элементов управления страницы, так как базовый отрисовщик не знает, что с ними делать. В противном случае будет отображена пустая страница. Таким образом, в этом примере метод ArrangeOverride вызывает метод Arrange в экземпляре Page.

Примечание.

Важно остановить и удалить объекты, которые предоставляют доступ к камере в приложении UWP. Невыполнение этого требования может помешать работе других приложений, которые пытаются получить доступ к камере устройства. Дополнительные сведения см. в статье об отображении предварительного изображения с камеры.

Итоги

В этой статье было показано, как создать пользовательский отрисовщик для страницы ContentPage, чтобы переопределять собственный способ отрисовки по умолчанию с помощью настройки в зависимости от платформы. ContentPage — это визуальный элемент, который отображает одно представление и занимает большую часть экрана.