Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?.NET TIPS

Xamarin.FormsアプリでXAMLあるいはコードビハインドに、プラットフォームごとに異なる設定を簡便に記述するにはOnPlatformクラス/メソッドを使用する。

» 2016年08月17日 05時00分 公開
[山本康彦BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

対象:Visual Studio 2015以降


 Xamarin.Formsは、XAMLとC#を使ってAndroid/iOS/Windows向けのクロスプラットフォーム開発を行える開発環境だ。

 クロスプラットフォームといっても、プラットフォームによって画面を変えたいこともあるだろう。コントロールの色を変えたり、コントロール周囲の隙間の広さを変えたりしたいといった場合だ。そのようなプラットフォームごとの指定をするにはどうしたらよいだろうか? 本稿では、XAMLとC#のそれぞれで実現する方法を解説する。

 なお、本稿では、Visual Studio 2015 Update 3およびXamarin.Forms 2.0を使って解説している。バージョンによっては細部が異なる可能性があるので、ご承知おき願いたい。

プラットフォームごとにコントロールのプロパティを設定するには?

 OnPlatform<T>クラス(Xamarin.Forms名前空間)を使う。

 例えば、Labelコントロール(Xamarin.Forms名前空間)の文字色(TextColorプロパティ)をXAMLで変えるには、次のコードのようにする。TextColorプロパティをLabelコントロールの子要素として定義する書き方を使って、TextColorプロパティにOnPlatform<T>オブジェクトを指定するのだ。このとき、ジェネリックなOnPlatform<T>クラスの実際の型は、x:TypeArguments属性で指定する。

<Label Text="Welcome to Xamarin Forms!" 
        x:Name="Label1" FontSize="Large">
  <Label.TextColor>
    <OnPlatform x:TypeArguments="Color"
                iOS="Red"
                Android="#ccaa00"
                WinPhone="#ee00a2e8"
                />
  </Label.TextColor>
</Label>

Labelコントロールの文字色をプラットフォームに応じて変える例(XAML)
OnPlatform<T>オブジェクトの実際の型は、x:TypeArguments属性で指定する(ここではXamarin.Forms名前空間のColor構造体)。
プラットフォームごとの値は、iOS/Android/WinPhoneの各属性に指定する。実際の属性(ここではColor構造体)をXAMLで指定するときの変換規則が適用されるので、色の場合はこの例に示したような文字列が指定できる(色名/RGBの16進表記/ARGBの16進表記)。
なお、Windowsプラットフォーム用の属性名は、「Windows」ではなく「WinPhone」なので注意しよう。

 上と同じことをコードビハインドのC#で記述するには、次のコードのようにする。OnPlatform<T>オブジェクトを直接生成するのではなく、Deviceクラス(Xamarin.Forms名前空間)に用意されているOnPlatform<T>メソッドを使うのが一般的である。

Label1.TextColor
  = Device.OnPlatform<Color>(Color.Red,
      Color.FromRgb(0xcc, 0xaa, 0), Color.FromUint(0xee00a2e8)
    );

Labelコントロールの文字色をプラットフォームに応じて変える例(C#)
OnPlatform<T>メソッドの3つの引数は、順にiOS/Android/Windowsプラットフォームに適用されるものだ。
XAMLコードでは文字列から適切なオブジェクトに変換してもらえたが、コードビハインドに記述する場合は変換してもらえない。この例のように正しい型のオブジェクトを引数に指定しなければならない。
コンパイラは引数からOnPlatform<T>メソッドの型を推論できるので、この例ではOnPlatformの後ろの「<Color>」という型引数の記述は省略できる。

補足:コードビハインドでのOnPlatform

 DeviceクラスのOnPlatform<T>メソッドには引数が3つもあって、どの引数がどのプラットフォーム用なのか分かりにくい。そんなときは、次のコードの2番目の例のように名前付き引数を使うとよいだろう。

 また、次のコードの3番目の例のように、OnPlatform<T>クラスのインスタンスを直接生成してもよい(XAMLでの記述方法はこちらを利用している)。

// 【1】一般的な書き方
string s  = Device.OnPlatform("iOS", "Android", "Windows");

// 【2】名前付き引数で書くと、分かりやすい
string s = Device.OnPlatform(
             iOS: "iOS",
             Android: "Android",
             WinPhone: "Windows"
           );

// 【3】OnPlatform<T>クラスを直接インスタンス化してもよい
var s = new OnPlatform<string>()
            {
              iOS = "iOS",
              Android = "Android",
              WinPhone = "Windows",
            };

OnPlatform<T>の3通りの書き方(C#)

 なお、Deviceクラスには、引数にラムダ式を与えるOnPlatformメソッドもある。これには既定値を受け取るDefaultという引数もあるので、例えば次のコードのようにWindowsとそれ以外で処理を分けるといった使い方もできる。

string s;
Device.OnPlatform(
  WinPhone: () => s = "Windows!!",
  Default: () => s = "Not Windows"
);

引数にラムダ式をとるOnPlatformメソッドもある(C#)
このOnPlatformメソッドには、4番目の引数としてDefaultがある。引数全てがオプショナル引数になっているので、この例のようにプラットフォーム1つとDefaultだけといった指定も可能だ(前述のOnPlatform<T>メソッドは引数省略不可)。この例の場合、Windowsでは変数sに「"Windows!!"」が代入され、iOSとAndroidでは「"Not Windows"」が入ることになる。

実際の例

 実際の例として、画面に文字列を2つ表示し、片方はその色を、もう一方はその内容を、プラットフォームに応じて変えてみよう。

 ソリューションを新しく作るときに[Blank Xaml App (Xamarin.Forms Portable)]を選ぶ。そのPCLプロジェクトにある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:dotNetTips1154"
             x:Class="dotNetTips1154.MainPage">
  <!--<Label Text="Welcome to Xamarin Forms!"
           VerticalOptions="Center" HorizontalOptions="Center" />-->
  <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
    <Label Text="Welcome to Xamarin Forms!" 
           x:Name="Label1" FontSize="Large">
      <Label.TextColor>
        <OnPlatform x:TypeArguments="Color"
                    iOS="Red" Android="#ccaa00" WinPhone="#ee00a2e8" />
      </Label.TextColor>
    </Label>
    <Label FontSize="Large" TextColor="Blue">
      <Label.FormattedText>
        <FormattedString>
          <Span Text="Platform: " /><Span x:Name="Span1" />
        </FormattedString>
      </Label.FormattedText>
    </Label>
  </StackLayout>
</ContentPage>

プラットフォームに応じて画面の一部を変えるサンプルコード(XAML)
自動生成されたLabelコントロールをコメントアウトし、<StackLayout>要素以降を追加した。
最初の文字列(「"Label1"」という名前のLabelコントロール)では、最初に示したXAMLコード中に<OnPlatform>要素を書く方法で、プラットフォームごとに文字色を変えている。
2つ目の文字列の後半部分(「"Span1"」という名前のSpanコントロール)には、コードビハインドから文字列を設定する(後述)。

 上のXAMLコードだけで、1つ目の文字列はプラットフォームに応じて色が変わるようになっている。2つ目の文字列は、コードビハインドのMainPage.xaml.csファイルに次のようなコードを追加して、プラットフォームごとに表示を変えている。

public MainPage()
{
  InitializeComponent();

  string s = Device.OnPlatform(
                iOS: "iOS",
                Android: "Android",
                WinPhone: "Windows"
              );
  Span1.Text = s;
}

プラットフォームに応じて画面の一部を変えるサンプルコード(C#)
MainPage.xaml.csファイルのコンストラクタに、太字の部分を追加した。前述したOnPlatform<T>メソッドの3通りの書き方のうち、2番目の方法を使っている。
なお、OnPlatform<T>メソッドを使うサンプルコードということでコードビハインドに書いているが、このように文字列リテラルをセットするだけならば前述の文字色と同様にXAMLコードで書いてしまえばよい。

 これで実行してみると、次の画像のようになる。

実行結果(Visual Studio Emulator for Android)
実行結果(iOS Simulator for Windows)
実行結果(Mobile Emulator) 実行結果
上はVisual Studio Emulator for Androidでの実行結果。中はiOS Simulator for Windowsでの実行結果。下はMobile Emulator(Windows 10)での実行結果。なお、iOS Simulator for Windowsは本稿執筆段階でプレビュー段階となっている。使用方法については「XamarinアプリのMacでのビルドとiOS Simulator for Windows」を参照されたい。

まとめ

 Xamarin.FormsのPCLプロジェクト内でプラットフォームごとに処理を分けるには、OnPlatform<T>クラスを利用するとよい。XAMLコードでも、<OnPlatform>要素を使ってプラットフォームごとに属性を変えられる。

利用可能バージョン:Visual Studio 2015以降
カテゴリ:Xamarin 処理対象:Xamarin.Forms
関連TIPS:Xamarin.Forms:プロジェクトにXamlページを追加するには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。