효과 만들기Creating an Effect

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

효과는 컨트롤 사용자 지정을 간소화합니다. 이 문서에서는 컨트롤에 포커스가 있을 때 Entry 컨트롤의 배경 색을 변경하는 효과를 만드는 방법을 보여줍니다.Effects simplify the customization of a control. This article demonstrates how to create an effect that changes the background color of the Entry control when the control gains focus.

각 플랫폼별 프로젝트에서 효과를 만들기 위한 프로세스는 다음과 같습니다.The process for creating an effect in each platform-specific project is as follows:

  1. PlatformEffect 클래스의 서브클래스를 만듭니다.Create a subclass of the PlatformEffect class.
  2. OnAttached 메서드를 재정의하고 컨트롤을 사용자 지정하기 위한 논리를 작성합니다.Override the OnAttached method and write logic to customize the control.
  3. OnDetached 메서드를 재정의하고 필요한 경우 컨트롤 사용자 지정을 정리하기 위한 논리를 작성합니다.Override the OnDetached method and write logic to clean up the control customization, if required.
  4. 효과 클래스에 ResolutionGroupName 특성을 추가합니다.Add a ResolutionGroupName attribute to the effect class. 이 특성은 효과에 대한 회사 전체 네임스페이스를 설정하여 동일한 이름의 다른 효과와의 충돌을 방지합니다.This attribute sets a company wide namespace for effects, preventing collisions with other effects with the same name. 이 특성은 프로젝트당 한 번만 적용할 수 있습니다.Note that this attribute can only be applied once per project.
  5. 효과 클래스에 ExportEffect 특성을 추가합니다.Add an ExportEffect attribute to the effect class. 이 특성은 컨트롤에 적용하기 전에 효과를 찾기 위해 그룹 이름과 함께 Xamarin.Forms에서 사용되는 고유 ID로 효과를 등록합니다.This attribute registers the effect with a unique ID that's used by Xamarin.Forms, along with the group name, to locate the effect prior to applying it to a control. 특성은 컨트롤에 적용하기 전에 효과를 찾는 데 사용되는 두 개의 매개 변수, 효과의 형식 이름 및 고유한 문자열을 사용합니다.The attribute takes two parameters – the type name of the effect, and a unique string that will be used to locate the effect prior to applying it to a control.

그런 다음, 적절한 컨트롤에 연결하여 효과를 사용할 수 있습니다.The effect can then be consumed by attaching it to the appropriate control.

참고

각 플랫폼 프로젝트에서 효과를 제공하는 것은 선택 사항입니다.It's optional to provide an effect in each platform project. 하나가 등록되지 않은 경우 효과를 사용하려는 시도는 아무 작업도 수행하지 않는 null이 아닌 값을 반환합니다.Attempting to use an effect when one isn't registered will return a non-null value that does nothing.

샘플 애플리케이션은 포커스가 있는 경우 컨트롤의 배경색을 변경하는 FocusEffect를 보여줍니다.The sample application demonstrates a FocusEffect that changes the background color of a control when it gains focus. 다음 다이어그램은 샘플 애플리케이션에서 각 프로젝트의 책임과 이들 간의 관계를 보여줍니다.The following diagram illustrates the responsibilities of each project in the sample application, along with the relationships between them:

HomePageEntry 컨트롤은 각 플랫폼별 프로젝트에서 FocusEffect 클래스로 사용자 지정됩니다.An Entry control on the HomePage is customized by the FocusEffect class in each platform-specific project. FocusEffect 클래스는 각 플랫폼에 대한 PlatformEffect 클래스에서 파생됩니다.Each FocusEffect class derives from the PlatformEffect class for each platform. 그러면 다음 스크린샷과 같이 컨트롤에 포커스가 있는 경우 변경되는 Entry 컨트롤이 플랫폼별 배경색으로 렌더링됩니다.This results in the Entry control being rendered with a platform-specific background color, which changes when the control gains focus, as shown in the following screenshots:

각 플랫폼의 효과 만들기Creating the Effect on Each Platform

다음 섹션에서는 FocusEffect 클래스의 플랫폼별 구현을 설명합니다.The following sections discuss the platform-specific implementation of the FocusEffect class.

iOS 프로젝트iOS Project

다음 코드 예제는 iOS 프로젝트에 대한 FocusEffect 구현을 보여줍니다.The following code example shows the FocusEffect implementation for the iOS project:

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(EffectsDemo.iOS.FocusEffect), nameof(EffectsDemo.iOS.FocusEffect))]
namespace EffectsDemo.iOS
{
    public class FocusEffect : PlatformEffect
    {
        UIColor backgroundColor;

        protected override void OnAttached ()
        {
            try {
                Control.BackgroundColor = backgroundColor = UIColor.FromRGB (204, 153, 255);
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached ()
        {
        }

        protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged (args);

            try {
                if (args.PropertyName == "IsFocused") {
                    if (Control.BackgroundColor == backgroundColor) {
                        Control.BackgroundColor = UIColor.White;
                    } else {
                        Control.BackgroundColor = backgroundColor;
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

OnAttached 메서드는 UIColor.FromRGB 메서드를 사용하여 컨트롤의 BackgroundColor 속성을 연한 자주색으로 설정하고, 필드에서 이 색을 저장합니다.The OnAttached method sets the BackgroundColor property of the control to light purple with the UIColor.FromRGB method, and also stores this color in a field. 이 기능은 효과가 연결된 컨트롤에 BackgroundColor 속성이 없는 경우 try/catch 블록에서 래핑됩니다.This functionality is wrapped in a try/catch block in case the control the effect is attached to does not have a BackgroundColor property. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

OnElementPropertyChanged 재정의는 Xamarin.Forms 컨트롤의 바인딩 가능한 속성 변경에 응답합니다.The OnElementPropertyChanged override responds to bindable property changes on the Xamarin.Forms control. IsFocused 속성이 변경되는 경우 컨트롤의 BackgroundColor 속성은 컨트롤에 포커스가 있으면 흰색으로 변경되고, 그렇지 않으면 연한 자주색으로 변경됩니다.When the IsFocused property changes, the BackgroundColor property of the control is changed to white if the control has focus, otherwise it's changed to light purple. 이 기능은 효과가 연결된 컨트롤에 BackgroundColor 속성이 없는 경우 try/catch 블록에서 래핑됩니다.This functionality is wrapped in a try/catch block in case the control the effect is attached to does not have a BackgroundColor property.

Android 프로젝트Android Project

다음 코드 예제는 Android 프로젝트에 대한 FocusEffect 구현을 보여줍니다.The following code example shows the FocusEffect implementation for the Android project:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.Droid.FocusEffect), nameof(EffectsDemo.Droid.FocusEffect))]
namespace EffectsDemo.Droid
{
    public class FocusEffect : PlatformEffect
    {
        Android.Graphics.Color originalBackgroundColor = new Android.Graphics.Color(0, 0, 0, 0);
        Android.Graphics.Color backgroundColor;

        protected override void OnAttached()
        {
            try
            {
                backgroundColor = Android.Graphics.Color.LightGreen;
                Control.SetBackgroundColor(backgroundColor);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
            try
            {
                if (args.PropertyName == "IsFocused")
                {
                    if (((Android.Graphics.Drawables.ColorDrawable)Control.Background).Color == backgroundColor)
                    {
                        Control.SetBackgroundColor(originalBackgroundColor);
                    }
                    else
                    {
                        Control.SetBackgroundColor(backgroundColor);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

OnAttached 메서드는 SetBackgroundColor 메서드를 호출하여 컨트롤의 배경색을 연한 녹색으로 설정하고, 필드에서 이 색을 저장합니다.The OnAttached method calls the SetBackgroundColor method to set the background color of the control to light green, and also stores this color in a field. 이 기능은 효과가 연결된 컨트롤에 SetBackgroundColor 속성이 없는 경우 try/catch 블록에서 래핑됩니다.This functionality is wrapped in a try/catch block in case the control the effect is attached to does not have a SetBackgroundColor property. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

OnElementPropertyChanged 재정의는 Xamarin.Forms 컨트롤의 바인딩 가능한 속성 변경에 응답합니다.The OnElementPropertyChanged override responds to bindable property changes on the Xamarin.Forms control. IsFocused 속성이 변경되는 경우 컨트롤의 배경색은 컨트롤에 포커스가 있으면 흰색으로 변경되고, 그렇지 않으면 연한 녹색으로 변경됩니다.When the IsFocused property changes, the background color of the control is changed to white if the control has focus, otherwise it's changed to light green. 이 기능은 효과가 연결된 컨트롤에 BackgroundColor 속성이 없는 경우 try/catch 블록에서 래핑됩니다.This functionality is wrapped in a try/catch block in case the control the effect is attached to does not have a BackgroundColor property.

유니버설 Windows 플랫폼 프로젝트Universal Windows Platform Projects

다음 코드 예제는 UWP(유니버설 Windows 플랫폼) 프로젝트에 대한 FocusEffect 구현을 보여줍니다.The following code example shows the FocusEffect implementation for Universal Windows Platform (UWP) projects:

using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.UWP.FocusEffect), nameof(EffectsDemo.UWP.FocusEffect))]
namespace EffectsDemo.UWP
{
    public class FocusEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            try
            {
                (Control as Windows.UI.Xaml.Controls.Control).Background = new SolidColorBrush(Colors.Cyan);
                (Control as FormsTextBox).BackgroundFocusBrush = new SolidColorBrush(Colors.White);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }
    }
}

OnAttached 메서드는 컨트롤의 Background 속성을 녹청색으로 설정하고, BackgroundFocusBrush 속성을 흰색으로 설정합니다.The OnAttached method sets the Background property of the control to cyan, and sets the BackgroundFocusBrush property to white. 이 기능은 효과가 연결된 컨트롤에 이러한 속성이 없는 경우 try/catch 블록에서 래핑됩니다.This functionality is wrapped in a try/catch block in case the control the effect is attached to lacks these properties. 정리가 필요하지 않으므로 OnDetached 메서드에 의한 구현은 제공되지 않습니다.No implementation is provided by the OnDetached method because no cleanup is necessary.

효과 사용Consuming the Effect

Xamarin.Forms .NET 표준 라이브러리 또는 공유 라이브러리 프로젝트에서 효과를 사용하기 위한 프로세스는 다음과 같습니다.The process for consuming an effect from a Xamarin.Forms .NET Standard library or Shared Library project is as follows:

  1. 효과에 의해 사용자 지정되는 컨트롤을 선언합니다.Declare a control that will be customized by the effect.
  2. 컨트롤의 Effects 컬렉션에 추가하여 컨트롤에 효과를 연결합니다.Attach the effect to the control by adding it to the control's Effects collection.

참고

효과 인스턴스는 단일 컨트롤에만 연결할 수 있습니다.An effect instance can only be attached to a single control. 따라서 두 개의 컨트롤에서 사용하려면 효과를 두 번 확인해야 합니다.Therefore, an effect must be resolved twice to use it on two controls.

XAML에서 효과 사용Consuming the Effect in XAML

다음 XAML 코드 예제는 FocusEffect가 연결된 Entry 컨트롤을 보여줍니다.The following XAML code example shows an Entry control to which the FocusEffect is attached:

<Entry Text="Effect attached to an Entry" ...>
    <Entry.Effects>
        <local:FocusEffect />
    </Entry.Effects>
    ...
</Entry>

.NET 표준 라이브러리의 FocusEffect 클래스는 XAML에서 효과 사용을 지원하며, 다음 코드 예제에 표시됩니다.The FocusEffect class in the .NET Standard library supports effect consumption in XAML, and is shown in the following code example:

public class FocusEffect : RoutingEffect
{
    public FocusEffect () : base ($"MyCompany.{nameof(FocusEffect)}")
    {
    }
}

FocusEffect 클래스는 RoutingEffect 클래스를 서브클래스하며, 일반적으로 플랫폼에 따라 내부 효과를 래핑하는 플랫폼 독립적인 효과를 나타냅니다.The FocusEffect class subclasses the RoutingEffect class, which represents a platform-independent effect that wraps an inner effect that is usually platform-specific. FocusEffect 클래스는 기본 클래스 생성자를 호출하여 해상도 그룹 이름(효과 클래스의 ResolutionGroupName 특성을 사용하여 지정됨)의 연결과 효과 클래스의 ExportEffect 특성을 사용하여 지정된 고유 ID로 이루어진 매개 변수를 전달합니다.The FocusEffect class calls the base class constructor, passing in a parameter consisting of a concatenation of the resolution group name (specified using the ResolutionGroupName attribute on the effect class), and the unique ID that was specified using the ExportEffect attribute on the effect class. 따라서 Entry가 런타임 시 초기화되는 경우 MyCompany.FocusEffect의 새 인스턴스는 컨트롤의 Effects 컬렉션에 추가됩니다.Therefore, when the Entry is initialized at runtime, a new instance of the MyCompany.FocusEffect is added to the control's Effects collection.

동작을 사용하거나 연결된 속성을 사용하여 효과를 컨트롤에 연결할 수도 있습니다.Effects can also be attached to controls by using a behavior, or by using attached properties. 동작을 사용하여 효과를 컨트롤에 연결에 대한 자세한 내용은 재사용 가능한 EffectBehavior를 참조하세요.For more information about attaching an effect to a control by using a behavior, see Reusable EffectBehavior. 연결된 속성을 사용하여 효과를 컨트롤에 연결에 대한 자세한 내용은 효과에 매개 변수 전달을 참조하세요.For more information about attaching an effect to a control by using attached properties, see Passing Parameters to an Effect.

C#에서 효과 사용Consuming the Effect in C#

C#의 해당하는 Entry가 다음 코드 예제에 나와 있습니다.The equivalent Entry in C# is shown in the following code example:

var entry = new Entry {
  Text = "Effect attached to an Entry",
  ...
};

FocusEffect는 다음 코드 예제에서 설명한 것처럼 효과를 컨트롤의 Effects 컬렉션에 추가하여 Entry 인스턴스에 연결됩니다.The FocusEffect is attached to the Entry instance by adding the effect to the control's Effects collection, as demonstrated in the following code example:

public HomePageCS ()
{
  ...
  entry.Effects.Add (Effect.Resolve ($"MyCompany.{nameof(FocusEffect)}"));
  ...
}

Effect.Resolve는 지정된 이름에 대한 Effect를 반환하며, 이는 해상도 그룹 이름(효과 클래스의 ResolutionGroupName 특성을 사용하여 지정됨)의 연결과 효과 클래스의 ExportEffect 특성을 사용하여 지정된 고유 ID입니다.The Effect.Resolve returns an Effect for the specified name, which is a concatenation of the resolution group name (specified using the ResolutionGroupName attribute on the effect class), and the unique ID that was specified using the ExportEffect attribute on the effect class. 플랫폼에서 효과를 제공하지 않으면 Effect.Resolve 메서드에서 null이 아닌 값을 반환합니다.If a platform doesn't provide the effect, the Effect.Resolve method will return a non-null value.

요약Summary

이 문서에서는 컨트롤에 포커스가 있을 때 Entry 컨트롤의 배경색을 변경하는 효과를 만드는 방법을 설명했습니다.This article demonstrated how to create an effect that changes the background color of the Entry control when the control gains focus.