Xamarin.Forms 플랫폼 별 UI 및 C#코드 다르게 구현하기

Table of Content

Xamarin.Forms Android, iOS, UWP 등의 플랫폼에서 각기 다른 레이아웃과 C# 코드를 구현하는 방법을 정리해놓은 글.

 

XAML에서 플랫폼 별 UI 구현

Page, View 등에 대한 속성 요소 구문(Property Element Syntax)과 <OnPlatform>을 사용하여 플랫폼 별로 다르게 나타나는 UI를 만들 수 있다.

  • OnPlatform의 x:TypeArguments 속성에 입력값의 타입을 지정
  • <OnPlatform> 내의 <On>에 플랫폼 별로 다르게 나타낼 Page 또는 View의 속성 값을 지정

아래 예제는 플랫폼 별로 ContentPage 여백 및 Label의 여러 속성을 다르게 구현한 예제.

MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MyXamarinStudy" x:Class="MyXamarinStudy.MainPage">
    <!-- 플랫폼별 Page 여백 설정 -->
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="Android, UWP">0</On>
            <On Platform="iOS">0,20,0,0</On>
        </OnPlatform>
    </ContentPage.Padding>

    <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
        <Label x:Name="label">
            <!-- 플랫폼별 TextColor 설정 -->
            <Label.TextColor>
                <OnPlatform x:TypeArguments="Color">
                    <On Platform="Android, UWP">Red</On>
                    <On Platform="iOS">#0000FF</On>
                </OnPlatform>
            </Label.TextColor>

            <!-- 플랫폼별 TextDecorations 설정 -->
            <Label.TextDecorations>
                <OnPlatform x:TypeArguments="TextDecorations">
                    <On Platform="Android, UWP" Value="Underline"/>
                    <On Platform="iOS" Value="Strikethrough"/>
                </OnPlatform>
            </Label.TextDecorations>

            <!-- 플랫폼별 Font Size 설정 -->
            <Label.FontSize>
                <OnPlatform x:TypeArguments="x:Double">
                    <On Platform="Android, UWP">20</On>
                    <On Platform="iOS">30.5</On>
                </OnPlatform>
            </Label.FontSize>

            <!-- 플랫폼별 Text 설정 -->
            <Label.Text>
                <OnPlatform x:TypeArguments="x:String">
                    <On Platform="Android, UWP">Android, UWP</On>
                    <On Platform="iOS">iOS</On>
                </OnPlatform>
            </Label.Text>
        </Label>
    </StackLayout>
</ContentPage>

 

C# 코드에서 플랫폼 별 UI 구현

Xamarin.Forms C# 코드로 플랫폼 별 UI를 다르게 설정하기 위해 Device.OS 프로퍼티와  TargetPlatform 열거형을 사용했었지만 이젠 더 이상 사용하지 않는다. 이제 Device.RuntimePlatform을 사용해야 한다.

아래 예제는 XAML에서 Label을 추가한 후 C# 코드로 ContentPage 여백 및 Label의 여러 속성을 다르게 구현한 예제. 결과는 위의 예제와 같다.

MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MyXamarinStudy" x:Class="MyXamarinStudy.MainPage">
    <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
        <Label x:Name="label"></Label>
    </StackLayout>
</ContentPage>

MainPage.xaml.cs

using Xamarin.Forms;

namespace MyXamarinStudy
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();

            switch (Device.RuntimePlatform)
            {
                case Device.Android:
                    Padding = new Thickness(0);
                    label.TextColor = Color.Red;
                    label.TextDecorations = TextDecorations.Underline;
                    label.FontSize = 20;
                    label.Text = "Android, UWP";
                    break;

                case Device.UWP:
                    Padding = new Thickness(0);
                    label.TextColor = Color.Red;
                    label.TextDecorations = TextDecorations.Underline;
                    label.FontSize = 20;
                    label.Text = "Android, UWP";
                    break;

                case Device.iOS:
                    Padding = new Thickness(0, 20, 0, 0);
                    label.TextColor = Color.FromRgb(0, 0, 0xFF);
                    label.TextDecorations = TextDecorations.Strikethrough;
                    label.FontSize = 30.5;
                    label.Text = "iOS";
                    break;
            }
        }
    }
}

 

Dependency Service 사용

Dependency Service는 플랫폼 별로 특성화된 기능을 구현하기 위해 사용하는 클래스다. 플랫폼 별로 파일 입출력 방식을 서로 다르게 구현하는 경우와 같이 플랫폼 별로 각기 다른 방식으로 작동되어야 할 때 사용한다. 사용 방법은 다음과 같다.

  • 인터페이스 생성
  • 각 플랫폼 프로젝트(.Android, .iOS, .UWP)에서 Dependency 어셈블리 생성
  • 공유 프로젝트에서 DependencyService 호출

아래 예제는 Xamarin.Essentials를 사용하여 안드로이드에서는 디스플레이 정보를, iOS에서는 디바이스 정보를 출력하는 예제다. Xamarin.Essentials를 사용하려면 모든 프로젝트에 Xamarin.Essentials NuGet 패키지를 추가해야 한다.

아래 예제에서 MainPage 객체를 다른 클래스의 메소드로 넘겨 DisplayAlert() 메소드를 호출했는데… 보통 이렇게 DisplayAlert() 메소드를 출력하지는 않을 것이다. Dependency Service 사용 방법을 설명하기 위해 그렇게 했을 따름이다…

인터페이스 생성

플랫폼 별로 특성화된 기능을 구현하기 위해 인터페이스를 생성한다. 이 인터페이스는 Dependency Service에서 호출할 메소드 하나를 선언한다.

MyXamarinStudy.ISpecific.cs

namespace MyXamarinStudy
{
    public interface ISpecific
    {
        void DoIt(MainPage mainPage);
    }
}

각 플랫폼 프로젝트에서 Dependency 어셈블리 생성

MyXamarinStudy.Android.Specific.cs

using Xamarin.Forms;
using Xamarin.Essentials;
using MyXamarinStudy.Droid;

[assembly: Dependency(typeof(Specific))] // Dependency 어셈블리 생성
namespace MyXamarinStudy.Droid
{
    public class Specific : ISpecific
    {
        private MainPage mainPage;

        public void DoIt(MainPage mainPage)
        {
            this.mainPage = mainPage;

            mainPage.DisplayAlert("Information",
                "MainDisplayInfo: " + DeviceDisplay.MainDisplayInfo + "\n\n"
                + "Orientation: " + DeviceDisplay.MainDisplayInfo.Orientation + "\n"
                + "Rotation: " + DeviceDisplay.MainDisplayInfo.Rotation + "\n"
                + "Width: " + DeviceDisplay.MainDisplayInfo.Width + "\n"
                + "height: " + DeviceDisplay.MainDisplayInfo.Height + "\n"
                + "Density: " + DeviceDisplay.MainDisplayInfo.Density + "\n", "OK");
        }
    }
}

MyXamarinStudy.iOS.Specific.cs

using Xamarin.Forms;
using Xamarin.Essentials;
using MyXamarinStudy.iOS;

[assembly: Dependency(typeof(Specific))] // Dependency 어셈블리 생성
namespace MyXamarinStudy.iOS
{
    public class Specific : ISpecific
    {
        private MainPage mainPage;

        public void DoIt(MainPage mainPage)
        {
            this.mainPage = mainPage;

            mainPage.DisplayAlert("Information", 
                "Device: " + DeviceInfo.Model + "\n"
                + "Manufacturer: " + DeviceInfo.Manufacturer + "\n"
                + "Device Name: " + DeviceInfo.Name + "\n"
                + "Version: " + DeviceInfo.VersionString + "\n"
                + "Platform: " + DeviceInfo.Platform + "\n"
                + "Idiom: " + DeviceInfo.Idiom + "\n"
                + "Device Type: " + DeviceInfo.DeviceType + "\n", "OK");
        }
    }
}

UWP는 생략. MacOS에서 UWP 테스트를 할 수 없으므로…

공유 프로젝트에서 Dependency Service 호출

MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MyXamarinStudy" x:Class="MyXamarinStudy.MainPage">
    <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
        <Button x:Name="button" Text="Button" Clicked="Handle_Clicked"></Button>
    </StackLayout>
</ContentPage>

MainPage.xaml.cs

using Xamarin.Forms;

namespace MyXamarinStudy
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        void Handle_Clicked(object sender, System.EventArgs e)
        {
            // Dependency Service 호출
            DependencyService.Get<ISpecific>().DoIt(this);
        }
    }
}

 

댓글 남기기