読者です 読者をやめる 読者になる 読者になる

ぴーさんログ

だいたいXamarin.Formsのブログ

ちょっと未来のXamarin.Formsを試す(1.3.0 Technology Preview)

Xamarin Xamarin.Forms XAML C#

この記事は Xamarin Advent Calendar 2014 、兼 XAML Advent Calendar 2014 の9日目です。

この記事では Xamarin.Forms の時期バージョン(ver.1.3.0)で追加される機能の中から、 StylesTriggersについてXAMLC#のサンプル付きでご紹介します。また、アプリケーションのエントリ部分が変更されるので、その修正方法も併せてご紹介します。

  • ver.1.3.0で追加される機能
    • Xamarin.Forms.Application
    • Dynamic Resource
    • Styles
    • Triggers
    • Behaviors
    • etc...

WPFなどで既に存在する機能の追加が多く、使い方も基本的に同じようです。

XAML Advent Calendar から来た方へ

Xamarin ご存知でしょうか?よく知らない方のために軽〜くご説明いたします。

Xamarin とは

  • C#(.NET)で iOSAndroidMacアプリを開発できるSDK(有償)。
  • そのSDKを作っている会社の名前。

Xamarin.Forms とは

  • ワンソースでiOSAndroidWindows Phone の3プラットフォームの画面を作成できるフレームワーク
  • BindingやMessagingをサポートしMVVMなアプリ開発が可能。
  • XAMLでViewを定義可能。(ただしコントロールは独自)

Xamarin.Froms を更新する

記事中の環境は Mac & Xamarin Studio(Stableチャンネル)です。
執筆時点の Xamarin.Forms 1.3.0 はプレビュー版です、紹介した内容は正式版で変更される可能性があります。
実行結果はiOS Simulatorのみとなっています、お許しください。

新規にソリューションを作ります。 プロジェクトのテンプレートは「Blank APP (Xamarin.Forms Portable)」を選択します。

スクリーンショット 2014-11-29 20.34.58.jpg

Xamarin.Forms の更新

さて、安定版のXamarin.FormsはNuGetマネージャからダウンロード可能ですが、ver.1.3.0は現在プレビュー版であるため通常の手順では導入できません。そこで、Xamarin Forumからnupkgファイルをダウンロードし、NuGetパッケージマネージャに対してローカルディレクトリをリポジトリとして追加する必要があります。nuget.orgから取得できるようになりました。

各プロジェクトの「パッケージ」ディレクトリを右クリックして「Add Packages」を選択するとパッケージマネージャが開きます。

AddPackagesを選択.jpg

「Show pre-release packages」をチェックして「xamarin.forms」と検索してください。 安定板の他に「-pre」サフィックスの付いたパッケージが見つかりますので最新版に更新します。

NuGetマネージャ.jpg

更新に成功するパッケージのバージョンが上がります。(更新前はver.1.2.3.x)

更新後のパッケージバージョン.jpg

この作業を全てのプロジェクトで行います。

Xamarin.Forms.Application に対応する

プロジェクトテンプレートをXamarin.Forms.Applicationを使用するコードに修正します。 この変更により以下の機能が追加されます。

  • root pageの変更を容易化
  • Properties dictionaryを経由する永続的データストア
  • Sleep/Resume/Start イベント
  • アプリケーションレベルのresource dictionary

この対応をしないと XAMLからのView生成が失敗 します。 どうやらView要素がアプリケーションレベルのリソースディクショナリを検索できるようにするため、XAMLからのView生成処理が変更されているようです。

PCLプロジェクト

Appクラスを次のように修正します。

   public class App : Application
    {
        public App()
        {
            MainPage = new ContentPage
            {
                Content = new Label
                {
                    Text = "Hello, Forms !",
                    VerticalOptions = LayoutOptions.CenterAndExpand,
                    HorizontalOptions = LayoutOptions.CenterAndExpand,
                },
            };
        }

//     protected override void OnSleep()
//     {
//         base.OnSleep();
//     }

//     protected override void OnResume()
//     {
//         base.OnResume();
//     }

//     protected override void OnStart()
//     {
//         base.OnStart();
//     }
    }

AppクラスにXamarin.Forms.Applicationを継承させ、最初の画面をMainPageプロパティに格納します。 OnSleepOnResumeOnStartメソッドをoverrideするとライフサイクルイベントを捕まえられるようです。(今回は使いません)

iOSプロジェクト

AppDelegateクラスを次のように修正します。

   public partial class AppDelegate : Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            Forms.Init();
            LoadApplication(new App());
            return base.FinishedLaunching(app, options);
        }
    }

Androidプロジェクト

MainActivityクラスを次のように修正します。

   public class MainActivity : Xamarin.Forms.Platform.Android.FormsApplicationActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            Forms.Init(this, bundle);
            LoadApplication(new App());
        }
    }

Windows Phoneプロジェクト

今回の手順ではWindows Phoneプロジェクトは作成されませんが一緒に解説します。

MainPageクラスを次のように修正します。

   public partial class MainPage : Xamarin.Forms.Platform.WinPhone.FormsApplicationPage
    {
        public MainPage()
        {
            InitializeComponent();
            Forms.Init();
            LoadApplication(new App());
        }
    }

XAMLコードの修正も忘れずに。

<winPhone:FormsApplicationPage
    ...
    xmlns:winPhone="clr-namespace:Xamarin.Forms.Platform.WinPhone;assembly=Xamarin.Forms.Platform.WP8"
    >
</winPhone:FormsApplicationPage>


さあ、これでXamarin.Forms 1.3.0の新機能を使う準備が整いました。

Styles を試す

PCLプロジェクトに新しいファイルを追加してください。ファイルの種類は「Forms」カテゴリにある「Forms ContentPage Xaml」です。ファイル名はStylesPageにします。

新しいページを追加.jpg

XAML

PageのリソースディクショナリにStyleを追加します、書き方はWPFとほぼ同じです。

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XF13TPSample.StylesPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="LabelStyle" TargetType="Label">
                <Setter Property="Label.TextColor" Value="White" />
                <Setter Property="Label.BackgroundColor" Value="Gray" />
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="Center" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <ContentPage.Content>
        <Label
            Text="Hello Styles!"
            Style="{StaticResource LabelStyle}"
            />
    </ContentPage.Content>
</ContentPage>

x:Keyで名前を付けてStaticResourceDynamicResourceとして参照できるようにします。Labelに適用したいのでTargetTypeには"Label"を指定します。ちなみにx:Keyのインテリセンスが効きません。 Setterで文字色、背景色、水平位置、垂直位置を指定しています。Setterのプロパティ指定はクラス名.プロパティ名とした方がスムーズに解決できるそうですが、HorizontalOptionsのように省略しても反映されました。Setterが適用されない場合は省略せずに書いてみると良いかもしれません。 Labelの方ではStyleプロパティでリソースディクショナリのStyleをStaticResourceとして参照しています。

今回はなるべく単純なサンプルにするためSetterのみとしましたがTriggerBehaviorを持たせることもできます。また、他のStyleの内容を引き継ぐBasedOnプロパティも利用できます。

実行結果

Appクラスのコンストラクタ内をMainPage = new StylesPage ();と書き換えて実行するとこのような結果になります。Styleに記述されたプロパティ指定(文字色、背景色、水平位置、垂直位置)がきちんと反映されています。

Styles実行結果_iOS.jpg

cs

XAMLのContentPageをC#で再現すると次のようになります。比べてみると XAMLの方が断然分かりやすいですね!

           var style = new Style (typeof(Label));
            style.Setters.Add (new Setter{
                Property = Label.TextColorProperty,
                Value = Color.White
            });
            style.Setters.Add (new Setter{
                Property = Label.BackgroundColorProperty,
                Value = Color.Gray
            });
            style.Setters.Add (new Setter{
                Property = Label.HorizontalOptionsProperty,
                Value = LayoutOptions.Center
            });
            style.Setters.Add (new Setter{
                Property = Label.VerticalOptionsProperty,
                Value = LayoutOptions.Center
            });

            var label = new Label{
                Text = "Hello Styles!",
                Style = style
            };

            var page = new ContentPage
            {
                Content = label,
            };

Triggers を試す

Triggerクラスを使ってみます。「-pre1」の時点では他にEventTriggerDataTriggerMultiTriggerがあります。 Stylesのサンプルと同じように、PCLプロジェクトに新しいファイルを追加してください。ファイル名はTriggersPageにします。

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" x:Class="XF13TPSample.TriggersPage">
    <ContentPage.Content>
        <Switch
            HorizontalOptions="Center"
            VerticalOptions="Center"
            >
            <Switch.Triggers>
                <Trigger TargetType="Switch" Property="Switch.IsToggled" Value="true">
                    <Setter Property="Switch.Rotation" Value="90"/>
                </Trigger>
            </Switch.Triggers>
        </Switch>
    </ContentPage.Content>
</ContentPage>

Switchクラス(≒トグルボタン)のTriggersプロパティの中で直接Triggerを定義しています。このTriggerSwitchIsToggledプロパティがtrueの時に発動し、角度を90度に変更します。

実行結果

Appクラスのコンストラクタ内をMainPage = new TriggersPage ();と書き換えて実行するとこのような結果になります。スイッチがオンの時に向きが90度変わります。ぐりん

TriggersSample.gif

cs

こちらもXAMLC#で再現すると次のようになります。(これ書いてて思いましたがSwitchクラスってswitch-caseキーワードと被ってて使いづらいですね)

           var s = new Switch {
                HorizontalOptions = LayoutOptions.Center,
                VerticalOptions = LayoutOptions.Center
            };

            var trigger = new Trigger (typeof(Switch)) {
                Property = Switch.IsToggledProperty,
                Value = true,
            };

            trigger.Setters.Add (new Setter {
                Property = Switch.RotationProperty,
                Value = 90.0
            });

            s.Triggers.Add (trigger);

            var page = new ContentPage {
                Content = s
            };

まとめ

Styles導入によってXAMLの利用価値がグンと上がったように思います。個人的にはXAMLでアニメーションを定義できるようになったり、ResourceDictionaryを単独で定義できるようになるともっとステキだと思います。 という訳でみんなXamrinでもXAML書きましょう!


この記事で作成したプロジェクトをGitHubに上げておきました。一から作るのが面倒な方はダウンロードして遊んでみください。

参考

On Technology with Mitch Milam » 2014 » October » 09 (Xamarin.Forms.Application 対応手順)

Xamarin.Forms 1.3.0 Technology Preview - Xamarin Forums

Xamarin.Forms 1.3.0 Pre-release 1 - Xamarin Forums