Uno Platform が凄く面白そうなので紹介!
Published Dec 13 2019 03:59 AM 24.9K Views
Microsoft

Uno Platform を少し触ってみた感じ面白そうだと感じた部分を紹介したいと思います。

公式ページはこちらになります。

https://platform.uno/

簡単な説明

詳細は公式ドキュメントの What is the Uno Platform? にあるのでそちらを見ていただくとして個人的な解釈では UWP で開発した画面が、そのまま Android や iOS や Windows (当然ですが) や WebAssembly 上で動くといったものを目指してるものになります。

 

Xamarin.Forms も同じように XAML + C# の組み合わせでクロスプラットフォームアプリケーションを開発可能ですが、Uno Platform と比べて一番の違いは ContentControl があることだと思ってます。

WPF で登場したコンテンツモデルによって柔軟な見た目をコントロールで実現できるようになりました。Xamarin.Forms は XAML + C# で開発したものを、ネイティブコントロールにマッピングするということはしてくれていたのですが、このコンテンツモデルは持ち合わせていなかったので、例えば以下のような XAML は、Xamarin.Forms では実現できませんでした。

 

<Button HorizontalAlignment="Center" VerticalAlignment="Center">
    <StackPanel Orientation="Horizontal">
        <Ellipse Width="30" Height="30" Fill="Blue" />
        <TextBlock Text="Rich button!!" />
        <Ellipse Width="30" Height="30" Fill="Blue" />
    </StackPanel>
</Button>

 

実行するとボタンの中に青い丸と、テキストが並んだ状態で表示されます。(左から Android、UWP、WebAssembly)

clipboard_image_0.png

WPF、UWP と XAML での開発に慣れていた私は、無意識のうちにこの柔軟性をがあるのが XAML での開発だと思ってたので Xamarin.Forms による開発は若干不自由に感じていました。

どっちがいいというのは無いと思っていて、Xamarin.Forms はレンダラーによってコントロールをネイティブプラットフォームのコントロールにマッピングすることでクロスプラットフォームの開発を実現していて、Uno は UWP で書いたものを各プラットフォームで動くようにしたというアプローチの違いです。

 

WPF、UWP の開発のバックグラウンドがある人にとっては Uno Platform は、とてもとっつきやすいプラットフォームに仕上がってると思います。

プラットフォーム固有機能へのアクセス

プラットフォーム固有機能へのアクセス方法も提供されています。C# と XAML の両方で可能です。

C# のほうは #if で分岐したり partial class を使う例が紹介されていますが、コードが Shared プロジェクトにあることを考えると単に各プラットフォーム固有のプロジェクト(iOS, Droid, UWP, Wasm)に同じインターフェースを持った同名のクラスを作って、中身はプラットフォーム固有実装という形で対応できます。例えばユーザーに何かしらあったことを通知したいときに Android ではトースト、iOS ではアラート、UWP ではトースト通知、WebAssembly ではダイアログという形で実装した場合は、以下のようなクラスを各プロジェクトに用意します。

 

Android プロジェクト

 

using Android.App;
using Android.Widget;

namespace HelloUno
{
    public class Toast
    {
        public static void Show(string text)
        {
            Android.Widget.Toast.MakeText(Application.Context, text, ToastLength.Long).Show();
        }
    }
}

 

 

iOS プロジェクト

 

using UIKit;

namespace HelloUno
{
    public class Toast
    {
        public static void Show(string text)
        {
            var alert = UIAlertController.Create("Toast", text, UIAlertControllerStyle.Alert);
            alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, _ => { }));
            UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
        }
    }
}

 

UWP プロジェクト

 

using System.Linq;
using Windows.UI.Notifications;

namespace HelloUno
{
    public class Toast
    {
        public static void Show(string text)
        {
            var n = ToastNotificationManager.CreateToastNotifier();
            var content = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            var textNode = content.GetElementsByTagName("text").First();
            textNode.InnerText = text;
            n.Show(new ToastNotification(content));
        }
    }
}

 

WebAssembly 用プロジェクト

 

using System;
using Windows.UI.Popups;

namespace HelloUno
{
    public class Toast
    {
        public static async void Show(string text)
        {
            await new MessageDialog(text).ShowAsync();
        }
    }
}

 

iOS は手元にないので確認できていませんが、Android と UWP と WebAssembly では以下のようになります。

clipboard_image_1.png

clipboard_image_2.png

clipboard_image_3.png

実際には一部だけプラットフォーム固有処理に切り出したいというケースとかもあるので partial method でプラットフォーム固有部分を切り出すか、今回のような完全にプラットフォーム固有処理は別々に作る場合もプラットフォーム間で実装に差異が生まれないようい Shared に interface を定義して、各プラットフォームのプロジェクトで実装という形にすると思います。

 

XAML でのプラットフォーム固有機能を使う場合も上記ドキュメントにあるように XML 名前空間を使ってすっきりと書けます。さらに、xmlns:native_android="using:Android.Widget" といったようなネイティブのコントロールの名前空間を定義して、xmlns:android="http://uno.ui/android" のようなプラットフォーム固有機能を書く機能と組み合わせると、ネイティブのコントロールを明示的に置くこともできます。

 

以下のような XAML を書いて

 

<Page
    x:Class="HelloUno.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloUno"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:android="http://uno.ui/android"
    xmlns:native_android="using:Android.Widget"
    mc:Ignorable="d android">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Button HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click">
            <StackPanel Orientation="Horizontal">
                <Ellipse Width="30" Height="30" Fill="Blue" />
                <TextBlock Text="Rich button!!" VerticalAlignment="Center" Margin="10" />
                <android:Border>
                    <native_android:TextView Text="Android Native!!"/>
                </android:Border>
                <Ellipse Width="30" Height="30" Fill="Blue" />
            </StackPanel>
        </Button>
    </Grid>
</Page>

 

実行すると Android 側にだけ追加でテキストが表示されています。

clipboard_image_4.png

Uno Platform を使ってるアプリ

以下の Issue で Uno Platform を使ってるアプリが紹介されてます。興味があったら実際にインストールしてみるといいかもしれません。

https://github.com/unoplatform/uno/issues/18

まとめ

Uno Platform は、WPF や UWP をやっていた人が、これ欲しかったと思うようなクロスプラットフォームアプリケーション開発ツールになってます。

愚直に UWP の API を各ネイティブにマッピングしてるので、ソースコードを見てみると面白いです。

 

個人的なお勧めは Uno.UI フォルダー以下です。

https://github.com/unoplatform/uno/tree/master/src/Uno.UI

 

例えば ContentControl の UpdateContentTemplateRoot メソッドとか頑張ってコンテンツモデルを再現してる感じがうかがえます。

https://github.com/unoplatform/uno/blob/master/src/Uno.UI/UI/Xaml/Controls/ContentControl/ContentCon...

 

ということで Uno Platform は、これからも継続的にウォッチしていこうと思います。

 

 

 

 

Version history
Last update:
‎Dec 13 2019 03:59 AM
Updated by: