ぴーさんログ

だいたいXamarin.Formsのブログ

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配信されないかなー。

【Evolve 2016】Xamarin.Forms Previewerを試してみた!

Xamarin Evolve 2016のキーノートで遂に来ました!

念願のXAMLプレビューが!Xamarin.Formsに!

呼称は Xamarin.Forms Previewer だそうです。

というわけで早速試してみた様子がこちら

後でXamarin Studioを再起動したらAndroidもプレビュー出来るようになりました。(でもImage表示できてない気がする....まぁまだAplha版だし)

必要な環境はXamarin StudioのAlphaチャネル最新版とXamarin.Forms 2.3プレビュー版、そしてその前提環境としてXcodeを最新にしておく必要があるみたい。

もうちょっと詳しく

※Xamarin.Forms Previewerはまだ正式リリースされた機能ではないので、不安定だったりバギーだったりするかも知れません。その点はご留意ください。(2016/4/29現在)

Xamarin.Forms Previewerの公式情報をXamarinのブログで確認してみましょう。

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

You can get the Xamarin.Forms Previewer today from the alpha updater channel in Xamarin Studio for Mac. To use the Xamarin.Forms previwer, your project will need to reference Xamarin.Forms 2.3 prerelease NuGet.

ふんふん、必要なのは AlphaチャンネルMac版Xamarin StudioとXamarin.Forms 2.3のプレビュー版ですね。Visual StudioやUWPはおいおいサポートされるでしょう。

Xamarin StudioをAlphaチャンネルへ

メニューから「Xamarin Studio > Check for Updates」を開いてAlphaチャンネルに切り替えます。

f:id:ticktack623:20160429130930j:plain (画像はすでにAlphaチャンネルのものです)

更新データをダウンロード出来たらXamarin Studioを再起動。

Xcodeが古い場合はこちらも最新版に更新しておきます。更新後に一度Xcodeを起動して関連ツールの更新も忘れずに。

Xamarin.Fromsのプロジェクトを作成

Xamarin.Fromsの新規プロジェクト(PCL)を作成します。(Sharedプロジェクトで作ると.xmalファイルを編集出来なくなって詰みました)

f:id:ticktack623:20160429131245j:plain

f:id:ticktack623:20160429131254j:plain

ここで一度ビルドしてHello Worldが動くことを確認。(iOSシミュレータを再起動する必要があるかも)

各プロジェクトにXamarin.Forms 2.3プレビューを追加

各プロジェクトの「パッケージ」をダブルクリックしてNuGetパッケージマネージャを開きます。 「Show pre-release packages」をチェックして、「xamarin.forms」と検索すると、プレビュー版のXamarin.Formsが見つかるのでこれをAdd Packageします。(PCLプロジェクトでのNuGetパッケージの追加が失敗することがありました。その場合はXamarin.Forms一旦削除してから入れ直します。)

f:id:ticktack623:20160429131344j:plain

ここでも一度ビルドしてHello Worldが動くことを確認。

XAML Previewerを試す

PCLプロジェクトに「Forms ContentPage Xaml」を追加。

f:id:ticktack623:20160429131400j:plain

XAMLファイルの変更がプレビューに反映されない時は、プロジェクトをビルドしたりxamlファイルを開き直すと解消される模様です。

f:id:ticktack623:20160428175311j:plain