Connect(); 2018 年特別号

Volume 33 Number 13

クロスプラットフォーム開発 - Xamarin.Forms シェルの概要

David Ortinau; 2018 年特別号

Xamarin.Forms は、コード共有を最大化すると共に、すべてのネイティブ プラットフォーム API と UI コントロールに対するフル アクセスを提供するため、XAML と C# を好むクロスプラットフォーム開発者に人気のあるツールキットです。この機能を構成する技術と概念は、最初、爽快であると同時に紛らわしいものとなり得ます。実のところ、一部の開発者は最初いら立ちを感じます。Xamarin を選んだのは生産性向上のためであって、望まない面倒を抱えることは一番嫌だったのです。今年の Connect(); で、Xamarin.Forms シェルを紹介します。これは、モバイル アプリケーション開発のための新しい既定の出発点であり、複雑さを軽減し、生産性を向上させます。

名前からわかるように、本質的にシェルはすべてのアプリケーションに必要とされる基本的な UI 機能をサポートするコンテナーであるため、開発者はアプリケーションの主な動作に集中できるようになります。既存の iOS および Android のアプリケーションでも簡単にシェルを導入して、ナビゲーション、UI のパフォーマンス、拡張性の機能強化をすぐに活用できます。シェルを使用すると、次のメリットがあります。

  • アプリケーションの視覚的な構造を記述する単一の場所
  • 一般的なナビゲーション UI と、どこからでもディープ リンクで利用できるナビゲーション サービス
  • アプリ内の全体的な検索エクスペリエンスを向上させる統合検索ハンドラー
  • 既定で拡張性を持たせるという方針により、汎用性と柔軟性を強化

アプリ

どのプロジェクトでも最初に、構築するアプリケーションの構造について誰かが概要を描きます (頭の中に描くだけでなければよいのですが)。デザイン カンプで提供されている場合もあれば、用紙に鉛筆で書かれているだけの場合もあります。シェルを使用すると、そのコンテンツを取り上げて、実行するアプリケーション コンテナーに変換することは非常に容易になります。後は誰かがそのコンテナーにコンテンツと機能を追加するばかりになります。

この記事では、Tailwind Traders というモバイル ショッピング アプリケーションの例を取り上げます。これは、Xamarin.Forms シェル、Azure、Cognitive Services、他のいくつかの機能やサービスを使用する方法を示すため、チームが作成した新しい参照アプリケーションです。図 1 に示されている、優れたデザイン チームによって提供されたデザイン カンプを見てみましょう。

Tailwind Traders サンプル アプリのデザイン カンプ
図 1 Tailwind Traders サンプル アプリのデザイン カンプ

表示画面に示されているように、このアプリでは一般的に必要とされるすべての機能が提供されています。ログインと登録フロー、製品カテゴリと検索による閲覧エクスペリエンス、チェックアウト フローなどです。また、このアプリは、デバイスのカメラと Azure Custom Vision API の機能を活用して、製品をリアルタイムで識別します。

クイック スタート

シェルを使用してこのアプリケーションを迅速にスキャフォールディングしてみましょう。Visual Studio 2019 を開き、Xamarin.Forms でクロスプラットフォームの新しいアプリケーションを開始します。この記事では、シェルの機能を理解するため、空のプロジェクトを使用して、Tailwind Traders アプリの構造を構築します。

プロジェクト ファイルが生成されたら、App.xaml.cs を開き、MainPage が新しいシェルのインスタンスに設定されていることにご注目ください(シェル テンプレートは aka.ms/xf-shell-templates からダウンロードできます)。 構造上、これは、過去の一般的な Xamarin.Forms アプリケーションとの唯一の違いです。コードは次のようになります。

namespace TailwindTraders.Mobile
{
  public partial class App
  {
    public App()
    {
      InitializeComponent();
      MainPage = new AppShell();
    }
  }
}

.NET Standard ライブラリ プロジェクトのルートにある AppShell.xaml を開くと、図 2 に示すとおりになります。

図 2 単一ページ Shell.xaml

<?xml version="1.0" encoding="UTF-8"?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:local="clr-namespace:TailwindTraders"
       RouteHost="tailwindtraders.com"
       RouteScheme="app"
       FlyoutBehavior="Disabled"
       Title="TailwindTraders"
       x:Class=" TailwindTraders.AppShell">
  <ShellItem>
    <ShellSection>
      <ShellContent>
        <local:MainPage/>
      </ShellContent>
    </ShellSection>
  <ShellItem>
</Shell>

このファイルを詳しく分析してみましょう。シェルは、3 つの階層的な要素で構成されます。それは、ShellItem、ShellSection、ShellContent です。ShellContent はすべて ShellSection の子であり、ShellSection は ShellItem の子です。これらのすべての部分は Shell に属します。これらは単独では UI を表すことはなく、アプリケーションのアーキテクチャの組織を表します。シェルは、これらの項目を使用して、実行されているプラットフォーム用の適切なナビゲーション UI を生成します。

  • ShellItem:ポップアップ内の項目によって表されているアプリケーションの最上位構造。複数の ShellSection を含めることができます。
  • ShellSection:下部のタブで移動可能なアプリケーション コンテンツのグループ。1 つまたは複数の ShellContent を含めることができ、複数の ShellContent は上部のタブで移動できます。
  • ShellContent:アプリケーションの ContentPages。

これらの 3 つの要素は、Tailwind Traders モバイル アプリケーションの視覚的な構造を記述するために使用できます。ログインと登録フローを無視して、コンテンツをホストするために ShellItem をいくつか追加します。これは、左側のポップアップ メニューとして表されます。

シェルの概念に、FlyoutItem、BottomTab、TopTab という名前を使用しないのはなぜかと思われるかもしれません。マイクロソフトのチームは、これについて多くのディスカッションを行った結果、Xamarin.Forms は、タブやメニューの厳密な概念を常に共有するとは限らない、既知および将来のプラットフォームに対応すると考えています。抽象的な名前を使用することにより、これらの要素がさまざまなプラットフォームをまたぐ一貫性のあるものとして表現されるべきなのか、それとも各プラットフォームのデザイン上の審美学に付き従うべきなのか、スタイルとテンプレート全体を通じて開発者が決定できるようにしています。この件に関するフィードバックをいつでもお寄せください。

図 3 に例を示します。ここで見ることができるのはポップアップのメニューです (UI の下の 3 分の 2 の部分)。ここには自動的に ShellItem が取り込まれます。これにより、アプリケーションのさまざまな領域に移動することができます。これらのアイテムに加え、ShellItem に関連付けられていないメニュー項目を明示的に追加できます。上部のポップアップ ヘッダー (2 つのボタン) には特別なコンテンツを表示します。これは、何であれこの領域に表示したいと思うもので構成できます。Shell.xaml 内でカスタム FlyoutHeader を宣言するには、このコードを使用します。

<Shell.FlyoutHeader>
  <local:FlyoutHeader />
</Shell.FlyoutHeader>

FlyoutMenu の要素
図 3 FlyoutMenu の要素

ヘッダー要素を使用すると、ユーザーが画面をスクロールするときの動作を制御できます。3 つのオプションがあります。

  • Fixed:ヘッダーは固定され、その下のコンテンツがスクロールします。
  • Scroll:メニュー項目と共にスクロールします。
  • CollapseOnScroll:スクロールすると、視差効果を持つスタイルで折りたたまれます。

この動作を調整するには、シェルの FlyoutHeaderBehavior プロパティを、直前に挙げた目的の値に設定します。ここでは、固定したままにするため、次のコードを使用します。

<Shell
  x:Class="TailwindTraders.Mobile.Features.Shell.Shell"
  FlyoutHeaderBehavior="Fixed"  
  ...            
  >             
  ...            
</Shell>

次に、コンテンツを設定してみましょう。デザインを見ると、ホーム画面、一連の製品カテゴリ、プロファイル、そして最後にログアウトの画面があることがわかります。まず、ホーム画面については、次の XAML コードを使用します。

<ShellItem Title="Home">
  <ShellSection>
    <ShellContent>
      <local:HomePage />
    </ShellContent>
  </ShellSection>
</ShellItem>

この XAML を徹底的に分析するため、アプリに HomePage を追加しました。これは、シェル ファイルで最初に宣言されているコンテンツであるため、起動する最初の ContentPage になります。これは、既存の Xamarin.Forms アプリケーションで使用する ContentPage 型と同じですが、ここではシェルのコンテキスト内でホストされています。

このデザインの場合、設定する必要があるのはタイトルのみですが、ShellItem には、項目の左側に表示されるイメージを提供できる FlyoutIcon プロパティも用意されています。アイコンには、任意の Xamarin.Forms ImageSource を使用することができます。

アプリを実行してみましょう。ホームページで、ハンバーガー アイコンをクリックして、ポップアップ メニューを開きます。このメニュー項目をタップすると、ホーム画面に移動できます (現時点でこれが唯一の画面です)。さらに多くの画面を追加しましょう。

次に、「祝日の飾り付け」や「アプライアンス」などの製品カテゴリを実装します。それぞれについて ShellItem を追加することもできますが、製品カテゴリ ページは異なるコンテンツを記載したまったく同じページであるため、機転を利かせることができます。シンプルな Menu­Item を使用して同じページに移動し、CommandParameter を使用してデータを渡して、ページの不要な重複を避けることができます。Shell.xaml に MenuItem を追加するためには、以下のコードを使用します。

<Shell.MenuItems>
  <MenuItem
    Command="{Binding ProductTypeCommand}"
    CommandParameter="1"
    Text="Holiday decorations" />
</Shell.MenuItems>

シェルの優れた特徴の 1 つは、データ バインディングをサポートしていることです。このケースでは、ビュー モデルでナビゲーションを実行可能な "Command" を使用しています。ShellItem と同じように、MenuItem はテキストとアイコンを使用します。また、ShellItem と同じように、シェルで MenuItemTemplate プロパティを設定してデザインをさらにカスタマイズするため、スタイルを設定することや、カスタム テンプレートを提供することさえできます。

タスクを完了させるため、各カテゴリにさらに多くのメニュー項目を追加できます。図 4 はすべてのメニュー項目のコードを示し、図 5 はアプリのポップアップ メニューでの視覚的な結果を示しています。

図 4 すべてのメニュー項目

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
  x:Class="TailwindTraders.AppShell"
  FlyoutHeaderBehavior="Fixed"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:local="clr-namespace:TailwindTraders.Views"
  Title="Tailwind Traders"
  x:Name="theShell"
  Route="tailwindtraders"
  RouteHost="microsoft.com"
  RouteScheme="app">
  <Shell.MenuItems>
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="1"
      Text="Holiday decorations" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="2"
      Text="Appliances" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="3"
      Text="Bathrooms" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="4"
      Text="Doors &amp; Windows" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="5"
      Text="Flooring" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="6"
      Text="Kitchen" />
    <MenuItem
      Command="{Binding ProductTypeCommand}"
      CommandParameter="7"
      Text="Storage" />
  </Shell.MenuItems>
  <ShellItem Title="Home">
    <ShellSection>
      <ShellContent>
        <local:HomePage />
      </ShellContent>
    </ShellSection>
  </ShellItem>
</Shell>

すべてのメニュー項目が表示されたポップアップ
図 5 すべてのメニュー項目が表示されたポップアップ

ページをさらに追加する

プロファイル ページをデザインからアプリに追加しましょう。新しい ContentPage をプロジェクトに追加してから、Shell.xaml ファイルに戻ります。HomePage に使用した XAML (図 4 を参照) をコピーして、それをプロファイル ページで置き換えることもできますが、HomePage はアプリケーションの起動中にすぐに作成されるため、アプリケーションが停止する可能性があります。アプリケーションのすべてのページが一度に読み込まれないようにするため、次のようにデータ テンプレートを使用します。

<ShellContent
  Title="Profile"
  ContentTemplate="{DataTemplate local:ProfilePage}" />

ShellContent のコンテンツ プロパティに直接 ContentPage を提供するのではなく、データ テンプレートを指定します。ユーザーが画面に移動すると、シェルは、要求されたページを動的にインスタンス化します。

この処理で注意すべきなのは、Home­Page とは異なり、ShellItem と ShellSection のラッパーを省略して、ShellContent に直接タイトルを配置したことです。これはずっと簡潔な方法であり、シェルはこれを自動的に処理する方法を認識して、必要な論理的ラッパーを提供します。これらのラッパーがツリーに UI ビューを導入しないことにご注意ください。シェルは、レンダリング速度とメモリ消費量を念頭に置いて記述されています。その結果、現在と同じコンテンツと UI をこの新しいシェル コンテキスト内でホストすると、Android OS におけるパフォーマンスへの影響は低く抑えられます。もちろん、最終的には開発者がアプリケーションの内部を設計しますが、シェルは出発点として優れた機能を備えています。

ポップアップのスタイルを設定する

他の XAML 要素の場合と同じように、CSS または XAML のスタイルを使用してシェルと FlyoutMenu の側面のスタイルを設定することができます。ポップアップ メニュー項目の表示方法をさらにカスタマイズする場合について考慮しましょう。図 3 のデザインを見ると、メニュー項目が他のシェル項目よりも太くなっています。

メニュー項目とシェル項目の表示は、DataTemplate をシェルに提供すると拡張できます。MenuItem はシェルの MenuItemTemplate を使用してポップアップ メニューに表示でき、ShellItem は ItemTemplate を使用して表示できます。これらの外観を完全に制御するには、各プロパティを、カスタム ContentView を含んだ DataTemplate に設定します。図 6 に示されているように、シェルは、タイトルとアイコンのバインド可能プロパティをテンプレート BindingContext に提供します。図 7 は視覚的な結果を示しています。

図 6 Shell.xaml で ShellItem の項目テンプレートをカスタマイズする

<Shell.ItemTemplate>
  <DataTemplate>
    <ContentView HeightRequest="32">
      <ContentView.Padding>
        <Thickness
          Left="32"
          Top="16" />
      </ContentView.Padding>
      <Label Text="{Binding Title}" />
    </ContentView>
  </DataTemplate>
</Shell.ItemTemplate>
<Shell.MenuItemTemplate>
  <DataTemplate>
    <ContentView HeightRequest="32">
      <ContentView.Padding>
        <Thickness
          Left="32"
          Top="16" />
      </ContentView.Padding>
      <Label Text="{Binding Text}" FontAttributes="Bold" />
    </ContentView>
  </DataTemplate>
</Shell.MenuItemTemplate>

ポップアップ項目テンプレート結果のイメージ
図 7 ポップアップ項目テンプレート結果のイメージ

項目のレンダラーをカスタマイズすることに加え、ラベルと 2 つのボタンがあるボックスを含む適切なヘッダーをポップアップに追加して、カメラの機能にすばやくアクセスできるようにします。その他のテンプレートと同じように、Shell.xaml ファイルの FlyoutHeaderTemplate にも追加します。コンテンツには任意の ContentView を使用できるため、図 8 のコードに示されているように、ここでは StackLayout を使用して子コントロールを垂直方向に配置します。いくつかのスタイルを追加してデザイン カンプに近づけ、アプリを実行すると、図 9 に示されているような結果が表示されます。シェル要素で FlyoutHeaderBehavior を設定すると、ユーザーが画面をスクロールする際に、ヘッダーが固定されるのか、スクロールするのか、折りたたまれるのかを決定できます。

図 8 FlyoutHeaderTemplate

<Shell.FlyoutHeaderTemplate>
  <DataTemplate>
    <StackLayout HorizontalOptions="Fill" VerticalOptions="Fill"
      BackgroundColor="White" Padding="16">
      <StackLayout.Resources>
        <Style TargetType="Button">
          <Setter Property="BackgroundColor" Value="White" />
          <Setter Property="BorderColor" Value="#2F4B66" />
          <Setter Property="BorderWidth">2</Setter>
          <Setter Property="CornerRadius">28</Setter>
          <Setter Property="HeightRequest">56</Setter>
          <Setter Property="Padding">
            <Thickness
              Left="24"
              Right="24" />
           </Setter>
         </Style>
       </StackLayout.Resources>
       <Label FontSize="Medium" Text="Smart Shopping">
         <Label.Margin>
           <Thickness Left="8" />
         </Label.Margin>
       </Label>
       <Button Image="photo" Text="By taking a photo">
         <Button.Margin>
           <Thickness Top="16" />
         </Button.Margin>
       </Button>
       <Button Image="ia" Text="By using AR">
         <Button.Margin>
           <Thickness Top="8" />
         </Button.Margin>
       </Button>
     </StackLayout>
   </DataTemplate>
 </Shell.FlyoutHeaderTemplate>

ヘッダーを含むポップアップのイメージ
図 9 ヘッダーを含むポップアップのイメージ

ナビゲーション

ここで、メニュー項目のページに移動するコマンドを実装します。これを行うため、シェルによって導入される新しい URI ベースのルーティングを使用します。URI を使用すると、ユーザーはアプリケーションの任意の部分に瞬時に移動することに加え、後戻りさえできるようになり、2 地点間のすべてのページを作成する必要がなくなります。これを行う方法を見てみましょう。

最初に、ルートを宣言します。次のように、アプリのスキームとホストから始めます。

<Shell
  Route="tailwindtraders"
  RouteHost="www.microsoft.com"
  RouteScheme="app"

これらの部分を URL にまとめると、次のような URI になります。app://www.microsoft.com/tailwindtraders

シェル ファイルに定義したシェルの各要素にはルート プロパティを指定でき、プログラムによる移動を行うために後でこれを使用できます。シェルの要素によって表されていないページについては、ルートを明示的に登録できます。ポップアップに追加するメニュー項目でそれを行います。各メニュー項目で ProductCategoryPage に移動し、そのページには特定のカテゴリに属する製品の一覧が表示されます。ルートの登録のコードを次に示します。

Routing.RegisterRoute("productcategory", typeof(ProductCategoryPage));

必要なルートの宣言を、Shell.cs のコンストラクターで、またはルートが呼び出されるより前に実行される任意の場所で行えるようになりました。次のコードに示されているように、メニュー項目は、必要なナビゲーションを実装するためのコマンドを公開します。

public ICommand ProductTypeCommand { get; } =
  new Command<string>(NavigateToProductType);
private static void NavigateToProductType(string typeId)
  {
    (App.Current.MainPage as Xamarin.Forms.Shell).GoToAsync(
      $"app:///tailwindtraders/productcategory?id={typeId}", true);
  }

シェルのもう 1 つの優れたメリットは、アプリケーションの任意の場所からアクセスできる静的ナビゲーション メソッドがあることです。ナビゲーション サービスが使用可能かどうかを心配したり、ビューからビュー モデルへ順に渡したり、すべてをラップするためにナビゲーション ページを追加したりする必要はなくなりました。今では、アプリケーション シェルへの参照を取得できるようになりました。アプリケーション シェルはアプリケーションの MainPage であり、App.Current のプロパティとしてアクセス可能です。これは、前のコード スニペットで確認できます。ナビゲーションを実行するには、GoToAsync メソッドを呼び出し、有効な URL を ShellNavigationState として渡します。ShellNavigationState は文字列または URI から構築できます。もう一度コードを見ると、GoToAsync では文字列のみを指定することができ、シェルによって ShellNavigationState のインスタンス化が行われることがわかります。

ビューとビュー モデルの間でデータを渡すには、querystring パラメーターを使用します。図 10 に示すとおり、適切なプロパティをクエリ プロパティ属性で修飾すると、シェルがこれらの値を直接 ContentPage か ViewModel 上に設定します。

図 10 クエリの属性の例

[Preserve]
[QueryProperty("TypeID", "id")]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProductCategoryPage : ContentPage
{
  private string _typeId;
  public ProductCategoryPage()
  {
    InitializeComponent();
    BindingContext = new ProductCategoryViewModel();
  }
  public string TypeID
  {
    get => _typeId;
    set => MyLabel.Text = value;
  }
}

QueryProperty は、受け取り側クラスからのパブリック プロパティ名 (この例では "TypeID") と、URL で使用される querystring パラメーター名 (この例では "id") を使用します。

戻る動作をインターセプトする

戻る操作をインターセプトすることはモバイル アプリ開発の一般的な要件で、Xamarin.Forms の課題となることがあります。シェルでは、この問題を軽減するため、必要な多数のカスタマイズの実装を完了する前と後に、ナビゲーション ルーティングへのフックを設けられるようになっています。ナビゲーションの処理の例を次に示します。まずは、XAML コードを使用してイベント ハンドラーを割り当てます。

<Shell           ...
  Navigating="Shell_Navigating"

その後、そのイベント ハンドラーに対して C# コードを使用します。

private void Shell_Navigating(object sender, ShellNavigatingEventArgs e)
{
  if (// Some Boolean evaluation)
  {
    e.Cancel(); // Do not allow this navigation AND/OR do something else
  }
}

シェルのインスタンスで、Navigating イベントにイベント ハンドラーを追加します。図 11 に示されているように、分離コードでは、ShellNavigatingEventArgs でナビゲーションの基本的な詳細事項を指定します。

図 11 ShellNavigatingEventArgs

要素 種類 説明
現在 ShellNavigationState 現在のページの URI。
ソース ShellNavigationState ナビゲーションの開始元を表す URI。
ターゲット ShellNavigationState ナビゲーションの宛先を表す URI。
CanCancel Boolean ナビゲーションをキャンセルできるかどうかを示すプロパティ。
キャンセル Boolean 要求されたナビゲーションをキャンセルするメソッド。
Canceled Boolean 現在のナビゲーションがキャンセルされたかどうかを示すプロパティ。

タブ、タブ、至る所にタブ

ポップアップ メニューは、ナビゲーションで一般的な UI パターンです。アプリケーション内のコンテンツの階層について検討する場合、ナビゲーションの上部または最も外側のレベルは、ポップアップ メニューです。その次の詳細レベルは、下部のタブです。ポップアップがない場合、通常、下部のタブがアプリケーション内のナビゲーションの最上位レベルと見なされます。次に、下部のタブ内でナビゲーションの次のレベルとなるのは、上部のタブです。そこから先は、相互にプッシュする単一のページです。これは、ナビゲーション UI を提供するためにシェルが採用している、こだわりのあるアプローチです。

下部のタブから始めましょう。単一の ShellItem の中に ShellSection が複数ある場合、それぞれを下部のタブとして表現することができます。アプリの下部のタブを作成する XAML コードの例を次に示します。

<ShellItem Title="Bottom Tab Sample" Style="{StaticResource BaseStyle}">
  <ShellSection Title="AR" Icon="ia.png">
    <ShellContent ContentTemplate="{DataTemplate local:ARPage}"/>
  </ShellSection>
  <ShellSection Title="Photo" Icon="photo.png">
    <ShellContent ContentTemplate="{DataTemplate local:PhotoPage}"/>
  </ShellSection>
</ShellItem>

このコードは、単一の ShellItem 内に 2 つの ShellSection があることを示しています。これらの ShellSection は、UI で、画面の下部にあるタブとして表示されます。ポップアップが必要ではない場合について考慮しましょう。ShellItem が 1 つだけの場合、FlyoutBehavior を "Disabled" に設定すると完全に非表示にできます。タブのスタイル設定は、既存のスタイル オプションを使用するか、カスタム レンダラーを指定して行えます。カスタマイズされたデータ テンプレートを使用できるポップアップ メニュー項目とは異なり、タブはもっと強くプラットフォームに左右されます。タブの色のスタイルを設定するには、次に示されているように、TabBar 項目のシェル クラスのスタイル プロパティを使用します。

<Style x:Key="BaseStyle" TargetType="Element">
  <Setter Property=
    "Shell.ShellTabBarBackgroundColor"
    Value="#3498DB" />
  <Setter Property=
    "Shell.ShellTabBarTitleColor"
    Value="White" />
  <Setter Property=
    "Shell.ShellTabBarUnselectedColor"
    Value="#B4FFFFFF" />
  </Style>

ShellItem にスタイル クラスを割り当てると、その色が同じセクション内のすべてのタブに適用されます。

次に、上部のタブについて説明します。上部のタブからコンテンツに移動できるようにするには、単一の ShellSection 内に複数の ShellContent 項目を追加します。スタイルの適用方法は、前に示した下部のタブの例と同様です。コードは次のようになります。

<ShellItem Title="Store Home" Shell.TitleView="Store Home"
  Style="{StaticResource BaseStyle}">
    <ShellSection Title="Browse Product">
      <ShellContent Title="Featured"
        ContentTemplate=
        "{DataTemplate local:FeaturedPage}" />
      <ShellContent Title="On Sale"
        ContentTemplate=
        "{DataTemplate local:SalePage}" />
    </ShellSection>
  </ShellItem>

ロードマップ

Xamarin.Forms シェルについては、ほかにもたくさんの機能があります。ナビゲーション バーや戻るボタンをカスタマイズする方法、これまでになく簡単に検索機能をページに追加できる、非常に強力な検索ハンドラーの詳細について説明を続けることもできたでしょう。現在、これらの機能に加え、さらに多くの機能が利用できるようになっており、安定版リリースが随時発表されるのに合わせてドキュメントが提供されます。

シェルのジャーニーは始まったばかりです。iOS と Android のアプリケーションの外観をほとんどまたはまったく同じにする必要がよくあるという話を Xamarin.Forms の開発者から聞いています。これに対処するため、サポートされているすべてのコントロールの開始点として、Google の Material Design のスタイルを適用する、シェルの実装であるマテリアル シェルをリリースする予定です。ネイティブのコントロールであることに変わりはないため、パフォーマンスや機能への悪影響はありません。

ナビゲーションの切り替えおよびセグエも準備中です。切り替えを使用すると、1 つのページから別のページに切り替える際のアニメーションを制御できます (左から右、右から左、クロスフェード、カールなど)。セグエは、宣言により「このボタンの動作が実行されたら、このルートを実行する」ことを示します。 これにより、GoToAsync ナビゲーション コードを記述する必要性が減り、物事どうしの接続方法が XAML でより明瞭に表現されます。切り替えとマテリアル シェルを組み合わせることにより、イメージ アイコンなどの要素が 1 つのページから別のページにシームレスに切り替わるヒーロー アニメーションなどの追加のアニメーションをいくつか使用できるようになります。

今すぐ確認する

Xamarin.Forms シェルは、現在 Xamarin.Forms 4.0 のプレビューでご利用いただけます。これには、CollectionView、CarouselView、まったく新しい Material Visual などの優れた新機能が含まれ、プラットフォーム固有の空のポイントではなく、一貫性のある一般的な UI スタイル ポイントから Xamarin.Forms アプリケーションを開始することがこれまで以上に簡単になりました。Visual Studio の NuGet パッケージ マネージャーを使用して、プレリリース版のオプションを切り替えることによりバージョン 4.0-pre1 に更新できます。

さらにわかりやすくするため、シェルに統合されたプロジェクト テンプレートの更新パッケージを作成しました。これには、既定でバージョン 4.0-pre が備わっています。テンプレートを aka.ms/xf-shell-templates からダウンロードしてインストールします。これが完了すると、新しい Xamarin.Forms プロジェクトを作成するときに、新しいシェルを利用したテンプレートが利用できるようになります。

Visual Studio 2019 のプレリリース版と同様、Xamarin.Forms 4.0 とシェルも進化を続けています。フィードバックをお寄せください。aka.ms/xf-4-feedback から、ご意見ご感想をお知らせください。


David Ortinau は、Microsoft のモバイル開発者ツールのシニア プログラム マネージャーであり、Xamarin.Forms に注力しています。2002 年以降は .NET 開発者として、多数のプログラム言語に精通し、あらゆる業種の Web、環境、モバイルのエクスペリエンスを開発してきました。いくつかの技術系スタートアップ企業の立ち上げや独自のソフトウェア企業の経営を成功させてから、Ortinau は Microsoft に入社し、優れたアプリ エクスペリエンスを作成する開発者のために役立つツールを作成するという、自らの情熱を追求することにしました。コンピューターを使用したり、家族と一緒に過ごしたりしていないときは、森を疾走しています。

この記事のレビューに協力してくれたマイクロソフト技術スタッフの David Britch、Jason Smith に心より感謝いたします。


この記事について MSDN マガジン フォーラムで議論する