ぴーさんログ

だいたいXamarin.Formsのブログ

Realm Xamarinを試してみた

5/10にRealmのXamarin対応版が公開されたので試してみました。

Realm Xamarinを公開! - Realm is a mobile database: a replacement for SQLite & Core Data

RealmはSQLiteやCoreDataから置き換わることを目標とするモバイルデータベースです。

Realm Xamarin自体はまだベータ版といったところですが、データベースエンジン自体は先にリリースされているJava版、Objective‑C版、Swift版と同じらしいので安心ですね。

という訳でRealm Xamarinを試すにあたってSQLiteが使われているTodoアプリのサンプルをRealmバージョンに改造してみました。

ソースコードGitHubに置いてあります。

P3PPP/xamarin-todo-with-realm

使ってみた感想

現時点ではRealmへのLinqクエリサポートが不完全なため満足なフィルタリングが使えません。実践投入するのは少なくともWhererがサポートされてからが良いでしょう。

Realmが管理中のオブジェクトはトランザクション外での変更が禁止されているので、うっかり双方向Bindingに繋げると死にます。編集画面を開いている間中トランザクションを開きっぱなしにするか、編集用のViewModelを用意する事になりそう。

サンプルの改造点

各プロジェクトでNuGetパッケージを追加、更新。 (Xamarin.Forms 2.2.0、Realm 0.74.1)

PCLプロジェクトを修正。

TodoItem.cs

SQLite版ではIDプロパティをオートインクリメントにしていますが、現時点ではRealmがオートインクリメントに対応していないそうなので、intからstringに変更してGUIDを使うことにしました。

TodoItemDatabase.cs

基本的にSQLite DBの操作をRealmに置き換え。

ただし、現時点ではRealmへのLinqクエリでWherer等のサポートが不完全なため、いったんToList()してから改めてフィルタリングしています。

App.cs

TodoItem.IDをstring型に変更した関係でApp.csも一部修正。

Views/TodoItemListX.xaml.cs

SQLite版を踏襲すると TodoItemListX.xaml.csでTodo編集ページのBindingContextにTodoItemを渡すことになります。 そのまままでは、双方向BindingでプロパティSetterが呼ばれて死ぬので一工夫必要です。 (Realmが管理中のRealmObjectはトランザクション外での編集禁止)

今回は編集用のコピーを作ってBindingContextにセットしています。

JXUGC #13 東京でLTしてきました

2016/5/7(土)に開催された「JXUGC #13 東京 緊急開催 Xamarin のすべて!」でLTしてきました。

今回のJXUGカンファレンスは参加人数がとても多く(約150人の定員に倍以上の応募!)、LT枠を含めた参加者は別室に詰めてました。ストリーミングでセッションを観ながらあーだこーだ言ってるのが思いの外楽かったので、「教師&生徒」スタイルではなく参加者全員でワイワイ進める勉強会をやったら面白そうです。

「ごちうサーチ」のアイコンを描きました

本日公開されたMacストアアプリ「ごちうサーチ」のアイコンを描いてました。

Macを使ってる人達は今すぐゲットだ!

ごちうサーチ を Mac App Store で




いきさつ


  • 動画の再生位置を探すアプリ → シークバー
  • ごちうさ → 兎とコーヒー

「シークバーの現在位置がカップに入った兎」というアイディアが浮かんだので作ってみる


Macアプリらしいアイコンの作り方を調べながら試行錯誤...


一晩明け、意匠に「ラテアート」を取り入れることを思いつく

f:id:ticktack623:20160506221815p:plain:w400

(シークバーは破線状に、全体としては真上から見たコーヒーカップのように)


最終的にアプリアイコンになった物がこちら


とまぁ、こんな感じで作られましたとさ。

【Xamarin.Forms 2.3プレビュー】Xamarin.Forms Themesを触ってみた

Evelve 2016で紹介されたXamarin.Forms Themesが(ようやく)NuGetに配信されました。 中身のdllを見る限り、現時点ではiOSAndroidのみ対応しているようですね。

早速試した方がいらっしゃいます!

Xamarinメモ その18 Xamarin.Forms.ThemesをPrism.Unity.Formsと併用する場合の注意 – A certain engineer "COMPLEX"

僭越ながら補足させていただくと...

補足1

App.xamlの追加方法は @omanuke さんの記事を参考にすると良いでしょう。

補足2

「assemblyがロードされない場合」が発生する理由は、XAMLしか参照していないassemblyはリンカが依存関係を検出できないためアプリパッケージにプラットフォーム実装dllが含まれなくなるからです。

よって、コードビハインドでテーマのResourceDictionaryを追加するか、公式ドキュメントのようにダミーコードを入れることで回避できます。単にテーマを使いたいだけならAppクラスのコンストラクタResources = new Xamarin.Forms.Themes.DarkThemeResources(); とするのが簡単です。

Xamarin.Forms Themesの中身

Themesは2種類のNuGetパッケージで構成されています。

  • Xamarin.Forms.Theme.Base
  • Xamarin.Forms.Theme.Light / Dark

それぞれどいう役割なのか少し覗いてみました。

Xamarin.Forms.Theme.Base

Baseには色などのリソースは定義されておらず、以下の物を提供します。

  • 角丸やシャドウなどのスタイルを適用するためのEffect
  • Effectの設定値(影の大きさ等)を保持するためのAttachedProperty

まさに Xamarin.Formsの公式ブログ で紹介されていたようなカスタムスタイルですね。

Xamarin.Forms.Theme.Light / Dark

以下のものを内包したカスタムResourceDictionaryを提供します。

  • カラーテーマ
  • カラーテーマに基づく、標準コントロールのスタイル
  • 標準コントロールの拡張スタイル(角丸Imageなど、StyleClassで適用)
  • DataPagesのコントロール用のDataTemplate

個人的にはDataPagesコントロール用のDataTemplateは別のdllにした方が良いように思うんですが...

ThemesとDataPegesを合わせてAndroidのマテリアルデザインのような物を作ろうとしているのでしょうか。

感想

統一感のあるクールなUIを簡単に構築できるのはとても魅力的です。 一方、リソースキーやスタイルクラスの名前を知らないと、使用やカスタマイズできないのが辛いように思えます。(ドキュメントとして公開されるか、ソース解析しないとわからない。)

Xamarin.Formsでプラットフォーム固有実装を扱う手段が増えてきたので整理してみる

Xamarin.Formsのリリースから約2年、当初よりもプラットフォームごとのカスタマイズ手段が増えてきたので、ここでちょっと整理してみようと思います。

目次

他に忘れてる物があったら教えてください。

  • OnPlatform (XF 1.0 ~)
  • DependecyService (XF 1.0 ~)
  • Plugins for Xamarin
  • Custom Renderer (XF 1.0 ~)
  • Effects (XF 2.1 ~)
  • Native Embedding (XF 2.2 ~)

OnPlatform

プラットフォーム毎に個別の処理をしたり、値を返すのに使います。 PCL、Shared、XAMLどの場面でも使えて、個別にパラメータを設定するのに活躍します。

DependecyService

DependecyServiceは一種のDIサービスです。 テキスト読み上げのような、プラットフォーム固有APIを呼ぶサービスを実装するのに向いていると思います。

  • 共通プロジェクトにInterfaceを定義
  • プラットフォームプロジェクトでInterfaceを実装をしてDependencySeviceに登録
  • 共通プロジェクトでDependencyServiceから固有実装のインスタンスを取得

f:id:ticktack623:20160501172735p:plain

Plugins for Xamarin

「Bait and Switch」と呼ばれるトリックを利用してクロスプラットフォームなライブラリを作る仕組みです。 実装方法がやや複雑ですがテンプレートが用意されているので大丈夫。(Visual Studio用)

DependecyService同様、プラットフォーム固有APIを呼ぶサービスを実装するのに向いていると思います。 こちらはXamrin.Formsに依存しておらず、Windowsをターゲットに含めることも可能です。

個人的にはDependecyServiceよりも、こちらでNuGetパッケージまで作ってしまうことをお勧めします。 (公開せずにローカルリポジトリで運用してもOK)

当ブログでも取り上げました。

Custom Renderer

Xamarin.FormsのViewは、抽象化されたビュー、レンダラー、ネイティブコントロールから成り立っており、レンダラーが抽象ビューに対応するネイティブコントロールの生成などを行っています。 この仕組みを使えば独自コントロールの作成から、既存コントロールのカスタマイズまであらゆる局面に対応可能です。(標準のPageやViewもこの仕組みで作られています)

反面、些細なカスタマイズには大げさで面倒だと言えます。

Effects

EffectsはXamarin.Forms 2.1から追加された、Viewのカスタマイズに最適な仕組みです。 Viewに添付されたEffectはXamarin.Forms側のコントロール、ネイティブ側のコントロール双方にアクセスすることができます。

生成済みコントロールに後付けする形で使用するため、インスタンス生成時の処理には介入できません。

当ブログでも取り上げました。

Native Embedding

Native EmbeddingはXamarin.Forms 2.2から追加された仕組みです。Evolve 2016のキーノートでも紹介されました。 Sharedプロジェクトに限り、Xamarin.Formsレイアウトの中にネイティブコントロールを混ぜ込むことができます。

Shared限定なので再利用性は低く、基本的にそのアプリケーション限定の利用となるでしょう。

当ブログでも取り上げました。

【Xamarin.Forms 2.2】Embedded Platform-Specific Controls in Xamarin.Forms

Xamarin.Forms 2.2から Layout.ChildrenContentView.Content に各プラットフォームのネイティブコントロールを埋め込めるようになり、Evolve 2016のキーノートでも紹介されました。 このフィーチャーを使うとCustomRendererよりもカジュアルにネイティブコントロールを利用できます。

キーノートのブログ

Live from Evolve: Faster and Easier Mobile App Development with Xamarin.Forms | Xamarin Blog

ドキュメント

Native Embedding - Xamarin

条件

ネイティブコントロールの埋め込みを行うにはSharedプロジェクト内のコードで、プラットフォーム毎に#ifディレクティブで記述します。PCLプロジェクトでは使用できません。

サンプルコード

次のようなコードをSharedプロジェクトに追加すると、ネイティブコントロールを埋め込む事ができます。

using System;
using Xamarin.Forms;

#if __IOS__
using Xamarin.Forms.Platform.iOS;
using UIKit;
#elif __ANDROID__
using Xamarin.Forms.Platform.Android;
using Android.Widget;
#endif

namespace XFApp25
{
    public class MyPage : ContentPage
    {
        public MyPage ()
        {
            var text = "Embedded Platform-Specific Control in Xamarin.Forms";

            var stackLayout = new StackLayout {
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
            };
#if __IOS__
            var uiLabel = new UILabel {
                MinimumFontSize = 14f,
                Lines = 0,
                LineBreakMode = UILineBreakMode.WordWrap,
                Text = text + "(iOS)",
            };
            // StackLayoutにUILabelが追加できる!
            stackLayout.Children.Add (uiLabel);
            // これもOK
            //Content = uiLabel.ToView ();
#elif __ANDROID__
            var textView = new TextView(Forms.Context) {
                Text = text + "(Android)",
                TextSize = 14,
            };
            stackLayout.Children.Add (textView);
            // これもOK
            //Content = textView.ToView ();
#endif
            Content = stackLayout;
        }
    }
}

仕組み

LayoutExtensionsクラスに定義された2つの拡張メソッドが使用します。

  • ToView - ネイティブコントロールをラップしてXamarin.FormsのViewに変換する拡張メソッド
  • Add - IList<View>、つまりLayout.Childrenに対する拡張メソッド(内部でToViewを呼ぶ)

これらの拡張メソッドを使うためには各名前空間の参照が必要です。

  • iOS – Xamarin.Forms.Platform.iOS
  • Android – Xamarin.Forms.Platform.Android
  • Windows Runtime – Xamarin.Forms.Platform.WinRT
  • Universal Windows Platform (UWP) – Xamarin.Forms.Platform.UWP

ToView拡張メソッドがネイティブコントロールを NaitiveViewWrapper に変換し、 NaitiveViewWrapperRenderer が汎用的なViewRendererとして働く、という具合ですね。 込み入ったコントロールのために、サイズ決定時に呼ばれるデリゲートなどを渡すことも出来ます。

【Xamarin.Forms 2.3プレビュー】Xamarin.Forms Themesを試そうとしたらまだ使えなかったので代わりにMerged Dictionaryの解説する

この記事はThemesの話のようでありながら、その実Xamarin.Forms版Merged Dictionaryの話です。

Xamarin.Forms Themes はEvolve 2016のキーノートで紹介された新機能の1つ、その目標は「デフォルトで美しいUIを提供すること」です。

Live from Evolve: Faster and Easier Mobile App Development with Xamarin.Forms | Xamarin Blog

すでにドキュメントも完備されてます。

Xamarin.Forms Themes - Xamarin

デフォルトとして提供されるLight/Darkテーマを使うにはNuGetからこれらをダウンロードします。

  • Xamarin.Forms.Theme.Base
  • Xamarin.Forms.Theme.Light / Dark

使い方はこんな感じ

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="EvolveApp.App"
             xmlns:light="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light">
    <Application.Resources>
        <ResourceDictionary MergedWith="light:LightThemeResources" />
    </Application.Resources>
</Application>

早速試そうとしたところ肝心のNuGetパッケージがまだ配信されていなかったので、代わりのThemesの前提となっている ResourceDictionary.MergedWith について解説します。

Xamarin.Forms版Merged Dictionary

ResourceDictionary.MergedWith はXamarin.Forms 2.3から追加されるプロパティです。他のResourceDictionaryクラスを指定することでリソースを連結します。おおよそWPFなどのMergedDictionariesに相当する機能ですね。

WPFなどWindowsXAMLプラットフォームとの比較

  • Windows
    • ResourceDictionary.MergedDictionaries はコレクション型で複数のResourceDictionaryを結合できる。
    • .xamlファイルを直接ResourceDictionaryとして指定できる。
  • Xamarin.Forms
    • ResourceDictionary.MergedWith に指定できるのは1個だけ。(プロパティの型はType)
    • .xamlファイルは指定できない、あくまでコンパイル可能なResourceDictionary派生型である必要がある。

Windows系は分割・集約、Xamarin.Formsは継承・カスタマイズに向いていると言えるでしょう。

さて、Themesの使い方と照らし合わせるとお気づきでしょうか?

そう、詰まるところXamarin.Forms Themesの正体はよくカスタムされたResourceDictionaryなのであります。 (StyleClass実装も含んでいるはずですが、その辺はThemesが使えるようになった際に改めて見ていきましょう)

Xamarin.Forms 2.3からはResourceDictionaryクラスのseald指定が外れるので自分でもThemeが作れます。

例えばこんな感じ

MyTheme.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="XFApp24.MyTheme">
    <Style TargetType="Label">
        <Setter Property="TextColor" Value="Red"/>
    </Style>
</ResourceDictionary>

MyTheme.xaml.cs

using Xamarin.Forms;

namespace XFApp24
{
    public partial class MyTheme : ResourceDictionary
    {
        public MyTheme ()
        {
            InitializeComponent ();
        }
    }
}

ContentPageなどのテンプレートから改造するとXAMLでカスタムResourceDictionaryが書けます。(要InitializeComponent)

これを使ってみると

f:id:ticktack623:20160430004453j:plain

XAMLプレビューにも反映されました。

早くNuGetにThemes配信されないかなー。