ContentPage 사용자 지정Customizing a ContentPage

샘플 다운로드 샘플 다운로드Download Sample Download the sample

ContentPage는 단일 보기를 표시하고 화면 대부분을 차지하는 시각적 요소입니다. 이 문서에서는 개발자가 자체적인 플랫폼별 사용자 지정을 통해 기본 네이티브 렌더링을 재정의할 수 있도록 ContentPage 페이지에 대한 사용자 지정 렌더러를 만드는 방법을 보여줍니다.A ContentPage is a visual element that displays a single view and occupies most of the screen. This article demonstrates how to create a custom renderer for the ContentPage page, enabling developers to override the default native rendering with their own platform-specific customization.

모든 Xamarin.Forms 컨트롤에는 네이티브 컨트롤의 인스턴스를 만드는 각 플랫폼에 대해 함께 제공되는 렌더러가 있습니다.Every Xamarin.Forms control has an accompanying renderer for each platform that creates an instance of a native control. iOS의 Xamarin.Forms 애플리케이션에서 ContentPage을 렌더링하면 PageRenderer 클래스가 인스턴스화되며, 차례로 네이티브 UIViewController 컨트롤이 인스턴스화됩니다.When a ContentPage is rendered by a Xamarin.Forms application, in iOS the PageRenderer class is instantiated, which in turn instantiates a native UIViewController control. Android 플랫폼에서 PageRenderer 클래스는 ViewGroup 컨트롤을 인스턴스화합니다.On the Android platform, the PageRenderer class instantiates a ViewGroup control. UWP(유니버설 Windows 플랫폼)에서 PageRenderer 클래스는 FrameworkElement 컨트롤을 인스턴스화합니다.On the Universal Windows Platform (UWP), the PageRenderer class instantiates a FrameworkElement control. Xamarin.Forms 컨트롤이 매핑되는 렌더러 및 네이티브 컨트롤 클래스에 대한 자세한 내용은 렌더러 기본 클래스 및 네이티브 컨트롤을 참조하세요.For more information about the renderer and native control classes that Xamarin.Forms controls map to, see Renderer Base Classes and Native Controls.

다음 다이어그램은 ContentPage 및 이를 구현하는 해당 네이티브 컨트롤 간의 관계를 보여줍니다.The following diagram illustrates the relationship between the ContentPage and the corresponding native controls that implement it:

렌더링 프로세스는 각 플랫폼에서 ContentPage에 대한 사용자 지정 렌더러를 만들어 플랫폼별 사용자 지정을 구현하는 데 활용할 수 있습니다.The rendering process can be taken advantage of to implement platform-specific customizations by creating a custom renderer for a ContentPage on each platform. 이 작업을 수행하는 프로세스는 다음과 같습니다.The process for doing this is as follows:

  1. Xamarin.Forms 페이지를 만듭니다.Create a Xamarin.Forms page.
  2. Xamarin.Forms에서 페이지를 사용합니다.Consume the page from Xamarin.Forms.
  3. 각 플랫폼의 페이지에 대한 사용자 지정 렌더러를 만듭니다.Create the custom renderer for the page on each platform.

라이브 카메라 피드 및 사진을 캡처하는 기능을 제공하는 CameraPage를 구현하기 위해 각 항목을 차례로 살펴보겠습니다.Each item will now be discussed in turn, to implement a CameraPage that provides a live camera feed and the ability to capture a photo.

Xamarin.Forms 페이지 만들기Creating the Xamarin.Forms Page

다음 XAML 코드 예제에 나온 대로 변경되지 않은 ContentPage를 공유 Xamarin.Forms 프로젝트에 추가할 수 있습니다.An unaltered ContentPage can be added to the shared Xamarin.Forms project, as shown in the following XAML code example:

<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에 대한 코드 숨김 파일을 다음 코드 예제에 표시된 것처럼 변경하지 않은 상태로 유지해야 합니다.Similarly, the code-behind file for the ContentPage should also remain unaltered, as shown in the following code example:

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

다음 코드 예제에서는 C#에서 페이지를 어떻게 만들 수 있는지를 보여줍니다.The following code example shows how the page can be created in C#:

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

CameraPage의 인스턴스는 각 플랫폼에서 라이브 카메라 피드를 표시하는 데 사용됩니다.An instance of the CameraPage will be used to display the live camera feed on each platform. 컨트롤의 사용자 지정은 사용자 지정 렌더러에서 수행되므로 CameraPage 클래스에서 추가 구현할 필요가 없습니다.Customization of the control will be carried out in the custom renderer, so no additional implementation is required in the CameraPage class.

Xamarin.Forms 페이지 사용Consuming the Xamarin.Forms Page

CameraPage가 Xamarin.Forms 애플리케이션에서 표시되어야 합니다.The empty CameraPage must be displayed by the Xamarin.Forms application. 이는 다음 코드 예제에 표시된 대로 MainPage 인스턴스의 단추를 탭하여 OnTakePhotoButtonClicked 메서드를 실행할 때 발생합니다.This occurs when a button on the MainPage instance is tapped, which in turn executes the OnTakePhotoButtonClicked method, as shown in the following code example:

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

이 코드는 간단히 CameraPage로 이동하여 사용자 지정 렌더러가 각 플랫폼에서 페이지의 모양을 사용자 지정합니다.This code simply navigates to the CameraPage, on which custom renderers will customize the page's appearance on each platform.

각 플랫폼에서 페이지 렌더러 만들기Creating the Page Renderer on each Platform

사용자 지정 렌더러 클래스를 만드는 프로세스는 다음과 같습니다.The process for creating the custom renderer class is as follows:

  1. PageRenderer 클래스의 서브클래스를 만듭니다.Create a subclass of the PageRenderer class.
  2. 네이티브 페이지를 렌더링하는 OnElementChanged 메서드를 재정의하고 페이지를 사용자 지정하는 논리를 작성합니다.Override the OnElementChanged method that renders the native page and write logic to customize the page. OnElementChanged 메서드는 해당 Xamarin.Forms 컨트롤이 생성될 때 호출됩니다.The OnElementChanged method is called when the corresponding Xamarin.Forms control is created.
  3. 페이지 렌더러 클래스에 ExportRenderer 특성을 추가하여 Xamarin.Forms 페이지를 렌더링하는 데 사용하도록 지정합니다.Add an ExportRenderer attribute to the page renderer class to specify that it will be used to render the Xamarin.Forms page. 이 특성은 사용자 지정 렌더러를 Xamarin.Forms에 등록하는 데 사용됩니다.This attribute is used to register the custom renderer with Xamarin.Forms.

참고

각 플랫폼 프로젝트에서 페이지 렌더러를 제공하는 것은 선택 사항입니다.It is optional to provide a page renderer in each platform project. 페이지 렌더러가 등록되지 않은 경우 페이지에 대한 기본 렌더러가 사용됩니다.If a page renderer isn't registered, then the default renderer for the page will be used.

다음 다이어그램은 샘플 애플리케이션에서 각 프로젝트의 책임과 이들 간의 관계를 보여줍니다.The following diagram illustrates the responsibilities of each project in the sample application, along with the relationship between them:

CameraPage 인스턴스는 각 플랫폼의 PageRenderer 클래스에서 모두 파생되는 플랫폼별 CameraPageRenderer 클래스에 의해 렌더링됩니다.The CameraPage instance is rendered by platform-specific CameraPageRenderer classes, which all derive from the PageRenderer class for that platform. 그러면 다음 스크린샷과 같이 각 CameraPage 인스턴스가 라이브 카메라 피드로 렌더링됩니다.This results in each CameraPage instance being rendered with a live camera feed, as shown in the following screenshots:

PageRenderer 클래스는 해당 네이티브 컨트롤을 렌더링하기 위해 Xamarin.Forms 페이지가 생성될 때 호출되는 OnElementChanged 메서드를 노출합니다.The PageRenderer class exposes the OnElementChanged method, which is called when the Xamarin.Forms page is created to render the corresponding native control. 이 메서드는 OldElementNewElement 속성이 포함된 ElementChangedEventArgs 매개 변수를 가져옵니다.This method takes an ElementChangedEventArgs parameter that contains OldElement and NewElement properties. 이러한 속성은 랜더러가 연결 Xamarin.Forms 요소와 렌더러가 연결되는 Xamarin.Forms 요소를 각각 나타냅니다.These properties represent the Xamarin.Forms element that the renderer was attached to, and the Xamarin.Forms element that the renderer is attached to, respectively. 샘플 애플리케이션에서 OldElement 속성은 null이고, NewElement 속성은 CameraPage 인스턴스에 대한 참조를 포함합니다.In the sample application the OldElement property will be null and the NewElement property will contain a reference to the CameraPage instance.

CameraPageRenderer 클래스에서 OnElementChanged 메서드의 재정의된 버전은 네이티브 페이지 사용자 지정을 수행하는 위치입니다.An overridden version of the OnElementChanged method in the CameraPageRenderer class is the place to perform the native page customization. 또한 렌더링되는 Xamarin.Forms 페이지 인스턴스에 대한 참조는 Element 속성을 통해 얻을 수 있습니다.A reference to the Xamarin.Forms page instance that's being rendered can be obtained through the Element property.

각 사용자 지정 렌더러 클래스는 렌더러를 Xamarin.Forms에 등록하는 ExportRenderer 특성으로 데코레이트됩니다.Each custom renderer class is decorated with an ExportRenderer attribute that registers the renderer with Xamarin.Forms. 이 특성은 렌더링되는 Xamarin.Forms 페이지의 형식 이름과 사용자 지정 렌더러의 형식 이름이라는 두 가지 매개 변수를 사용합니다.The attribute takes two parameters – the type name of the Xamarin.Forms page being rendered, and the type name of the custom renderer. 특성의 assembly 접두사는 특성이 전체 어셈블리에 적용되도록 지정합니다.The assembly prefix to the attribute specifies that the attribute applies to the entire assembly.

다음 섹션에서는 각 플랫폼에 대한 CameraPageRenderer 사용자 지정 렌더러의 구현을 설명합니다.The following sections discuss the implementation of the CameraPageRenderer custom renderer for each platform.

iOS에서 페이지 렌더러 만들기Creating the Page Renderer on iOS

다음 코드 예제에서는 iOS 플랫폼용 페이지 렌더러를 보여줍니다.The following code example shows the page renderer for the iOS platform:

[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 컨트롤을 인스턴스화합니다.The call to the base class's OnElementChanged method instantiates an iOS UIViewController control. 라이브 카메라 스트림은 렌더러가 기존 Xamarin.Forms 요소에 아직 연결되어 있지 않은 경우 및 사용자 지정 렌더러에 의해 렌더링된 페이지 인스턴스가 존재하는 경우에만 렌더링됩니다.The live camera stream is only rendered provided that the renderer isn't already attached to an existing Xamarin.Forms element, and provided that a page instance exists that is being rendered by the custom renderer.

페이지는 카메라의 라이브 스트림 및 사진을 캡처하는 기능을 제공하는 데 AVCapture API를 사용하는 일련의 메서드에 의해 사용자 지정됩니다.The page is then customized by a series of methods that use the AVCapture APIs to provide the live stream from the camera and the ability to capture a photo.

Android에서 페이지 렌더러 만들기Creating the Page Renderer on Android

다음 코드 예제에서는 Android 플랫폼용 페이지 렌더러를 보여줍니다.The following code example shows the page renderer for the Android platform:

[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 메서드에 대한 호출은 보기의 그룹인 Android ViewGroup 컨트롤을 인스턴스화합니다.The call to the base class's OnElementChanged method instantiates an Android ViewGroup control, which is a group of views. 라이브 카메라 스트림은 렌더러가 기존 Xamarin.Forms 요소에 아직 연결되어 있지 않은 경우 및 사용자 지정 렌더러에 의해 렌더링된 페이지 인스턴스가 존재하는 경우에만 렌더링됩니다.The live camera stream is only rendered provided that the renderer isn't already attached to an existing Xamarin.Forms element, and provided that a page instance exists that is being rendered by the custom renderer.

그런 다음, 페이지는 AddView 메서드가 호출되어 ViewGroup에 라이브 카메라 스트림 UI를 추가하기 전에, 카메라의 라이브 스트림 및 사진을 캡처하는 기능을 제공하는 데 Camera API를 사용하는 일련의 메서드를 호출하여 사용자 지정됩니다.The page is then customized by invoking a series of methods that use the Camera API to provide the live stream from the camera and the ability to capture a photo, before the AddView method is invoked to add the live camera stream UI to the ViewGroup. Android에서는 보기에서 측정값 및 레이아웃 작업을 수행하는 OnLayout 메서드도 재정의해야 합니다.Note that on Android it's also necessary to override the OnLayout method to perform measure and layout operations on the view. 자세한 내용은 ContentPage 렌더러 샘플을 참조하세요.For more information, see the ContentPage renderer sample.

UWP에서 페이지 렌더러 만들기Creating the Page Renderer on UWP

다음 코드 예제는 UWP용 페이지 렌더러를 보여줍니다.The following code example shows the page renderer for 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 컨트롤을 인스턴스화합니다.The call to the base class's OnElementChanged method instantiates a FrameworkElement control, on which the page is rendered. 라이브 카메라 스트림은 렌더러가 기존 Xamarin.Forms 요소에 아직 연결되어 있지 않은 경우 및 사용자 지정 렌더러에 의해 렌더링된 페이지 인스턴스가 존재하는 경우에만 렌더링됩니다.The live camera stream is only rendered provided that the renderer isn't already attached to an existing Xamarin.Forms element, and provided that a page instance exists that is being rendered by the custom renderer. 그런 다음, 페이지는 사용자 지정된 페이지가 표시를 위해 Children 컬렉션에 추가되기 전에, 카메라의 라이브 스트림 및 사진을 캡처하는 기능을 제공하는 데 MediaCapture API를 사용하는 일련의 메서드를 호출하여 사용자 지정됩니다.The page is then customized by invoking a series of methods that use the MediaCapture API to provide the live stream from the camera and the ability to capture a photo before the customized page is added to the Children collection for display.

UWP에서 PageRenderer로부터 파생되는 사용자 지정 렌더러를 구현하는 경우 기본 렌더러는 수행할 작업을 알 수 없으므로 ArrangeOverride 메서드 또한 페이지 컨트롤을 정렬하도록 구현되어야 합니다.When implementing a custom renderer that derives from PageRenderer on UWP, the ArrangeOverride method should also be implemented to arrange the page controls, because the base renderer doesn't know what to do with them. 그렇지 않은 경우 빈 페이지가 발생합니다.Otherwise, a blank page results. 따라서 이 예제에서 ArrangeOverride 메서드는 Page 인스턴스에서 Arrange 메서드를 호출합니다.Therefore, in this example the ArrangeOverride method calls the Arrange method on the Page instance.

참고

UWP 애플리케이션에서 카메라에 대한 액세스를 제공하는 개체를 중지 및 삭제하는 것이 중요합니다.It's important to stop and dispose of the objects that provide access to the camera in a UWP application. 이렇게 하지 않으면 디바이스의 카메라에 액세스하려고 하는 다른 애플리케이션을 방해할 수 있습니다.Failure to do so can interfere with other applications that attempt to access the device's camera. 자세한 내용은 카메라 미리 보기 표시를 참조하세요.For more information, see Display the camera preview.

요약Summary

이 문서에서는 개발자가 자체적인 플랫폼별 사용자 지정을 통해 기본 네이티브 렌더링을 재정의할 수 있도록 ContentPage 페이지에 대한 사용자 지정 렌더러를 만드는 방법을 설명했습니다.This article has demonstrated how to create a custom renderer for the ContentPage page, enabling developers to override the default native rendering with their own platform-specific customization. ContentPage는 단일 보기를 표시하고 화면 대부분을 차지하는 시각적 요소입니다.A ContentPage is a visual element that displays a single view and occupies most of the screen.