Xamarin.Forms:コントロールを等間隔に配置するには?:.NET TIPS
Xamarin.Formsアプリでは、StackLayout/Gridコントロールとそれらのプロパティを使うことで、とても簡単にコントロールを等間隔に配置できる。
対象:Visual Studio 2015以降
Xamarin.Formsは、XAMLとC#を使ってAndroid/iOS/Windows向けのクロスプラットフォーム開発を行える開発環境だ。
画面上の決められた領域の中でコントロールを等間隔に配置するには、どうしたらよいだろうか? もちろんGridコントロールを使って、その行/列のサイズを細かく調整していけば実現できるだろう。だが、Xamarin.Formsにはもっと簡単な方法があるのだ。本稿ではその方法を解説する。
等間隔に配置する2通りのパターン
コントロールを等間隔に並べるといっても、2通りのパターンがある(次の画像)。コントロールのサイズを一定にするか、間隔を一定にするかだ。
コントロールを等間隔で縦1列に配置する2通りのパターン
これはWindows 10(PC)で実行している。
画像左側のウィンドウの高さを大きくすると、右側のウィンドウになる。ウィンドウの左側では、黄色いコントロールの高さを一定に保ったまま、コントロール間の間隔が変化する。ウィンドウの右側では、黄色いコントロールの高さが変化し、コントロール間の間隔は一定のままだ。
縦1列(または横1列)に並べたコントロールのサイズを保ったまま間隔を可変とするには、StackLayoutコントロール(Xamarin.Forms名前空間)が利用できる。次に説明する。
間隔を一定に保ったままコントロールのサイズを可変にするのは、Gridコントロール(Xamarin.Forms名前空間)で簡単に実現できる。こちらは後で説明する。
コントロールのサイズを保って等間隔に配置するには?
StackLayoutコントロールを使い、StackLayoutコントロール用の特別な値をその内部に置いたコントロールのVerticalOptionsプロパティに設定するとよい。
コントロールのVerticalOptionsプロパティに設定できるLayoutOptions構造体(Xamarin.Forms名前空間)には、以下に示す4つの特別な値がある。これらは、StackLayoutコントロール内に配置したコントロールだけで有効だ。
- StartAndExpand: 縦並びではコントロールの下に(横並びでは右に)間隔を開ける
- CenterAndExpand: 縦並びではコントロールの上下に(横並びでは左右に)間隔を開ける
- EndAndExpand: 縦並びではコントロールの上に(横並びでは左に)間隔を開ける
- FillAndExpand: 縦並びではコントロールを上下に(横並びでは左右に)拡張する*1
*1 FillAndExpandを指定すると、間隔が一定になる(StackLayoutコントロールのSpacingプロパティに設定した値になる)。間隔を一定に保ったままコントロールのサイズを可変とするには、後で説明するGridコントロールによる方法の他に、このFillAndExpandを使ってもよい。
コントロールのサイズを保って等間隔に配置するには、1つ目のコントロールのVerticalOptionsプロパティにはStartを指定し、残りのコントロールのVerticalOptionsプロパティにはEndAndExpandを指定する(次のコード)。1つ目のコントロールにもEndAndExpandを指定してしまうと、その上にもすき間が開いてしまうので注意しよう。
<StackLayout Padding="30">
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="Frame">
<!-- それぞれのFrameコントロールの上に間隔を均等に配置 -->
<Setter Property="VerticalOptions" Value="EndAndExpand" />
<Setter Property="OutlineColor" Value="Accent" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<!-- 最初のFrameコントロールだけは、余白なしにする -->
<Frame VerticalOptions="Start"><Label>AAA</Label></Frame>
<!-- 以降のFrameコントロールにはStyleで定義したEndAndExpandが適用される -->
<Frame><Label>BBB</Label></Frame>
<Frame><Label>CCC</Label></Frame>
<Frame><Label>DDD</Label></Frame>
</StackLayout>
これで冒頭の画像のウィンドウの左側に近いレイアウトになる。サンプルが簡潔になるように細部を省略してあるので、冒頭の画像と同じにはならない(完全なコードは最後に紹介する)。
なお、Frameコントロール(Xamarin.Forms名前空間)の意味合いが、WPFアプリ/UWPアプリの同名コントロールとはずいぶん違う。WPFアプリ/UWPアプリのBorderコントロールに近いものだ。
間隔を一定に保って等間隔に配置するには?
StackLayoutコントロールでFillAndExpandを指定してもよいが、GridコントロールのRowSpacingプロパティ/ColumnSpacingプロパティを使っても簡単にできる。縦並びのときはRowSpacingプロパティを設定する(次のコード)。
<Grid RowSpacing="10" Padding="30">
<Grid.Resources>
<ResourceDictionary>
<Style TargetType="Frame">
<Setter Property="OutlineColor" Value="Accent" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Frame><Label>000</Label></Frame>
<Frame Grid.Row="1"><Label>111</Label></Frame>
<Frame Grid.Row="2"><Label>222</Label></Frame>
<Frame Grid.Row="3"><Label>333</Label></Frame>
</Grid>
これで冒頭の画像のウィンドウの右側に近いレイアウトになる。サンプルが簡潔になるように細部を省略してあるので、冒頭の画像と同じにはならない(完全なコードは次に紹介する)。
なお、このようにGridコントロールを均等に分割する(全ての<RowDefinition>要素でHeight="*"とする)場合には、<Grid.RowDefinitions>要素は省略できる。
実際の例
実際の例として、冒頭の画像で紹介した画面のXAMLコードを示しておこう。
ソリューションを新しく作るときに[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:dotNetTips1158"
x:Class="dotNetTips1158.MainPage">
<!--<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />-->
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0" />
</ContentPage.Padding>
<Grid ColumnSpacing="20">
<!-- 均等分割なら、ColumnDefinitionsは省略可能 -->
<!--<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>-->
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!-- 以降が均等分割だけなら、以降のRowDefinitionを省略可能 -->
<!--<RowDefinition Height="*" />-->
</Grid.RowDefinitions>
<Label Text="StackLayout" HorizontalOptions="Center" VerticalOptions="Center" />
<!-- 【画面左側】コントロールのサイズを保って等間隔に配置する -->
<StackLayout Grid.Row="1" BackgroundColor="#2200ff00" Padding="10">
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="Frame">
<!-- それぞれのFrameコントロールの上に間隔を均等に配置 -->
<Setter Property="VerticalOptions" Value="EndAndExpand" />
<Setter Property="BackgroundColor" Value="Yellow" />
<Setter Property="OutlineColor" Value="Green" />
</Style>
<Style TargetType="Label">
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="TextColor" Value="Black" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<!-- 最初のコントロールだけは、余白なしにする -->
<Frame VerticalOptions="Start"><Label>AAA</Label></Frame>
<Frame><Label>BBB</Label></Frame>
<Frame><Label>CCC</Label></Frame>
<Frame><Label>DDD</Label></Frame>
</StackLayout>
<Label Grid.Column="1" Text="Grid"
HorizontalOptions="Center" VerticalOptions="Center" />
<!-- 【画面右側】間隔を一定に保って等間隔に配置する -->
<Grid Grid.Row="1" Grid.Column="1" BackgroundColor="#2200ffff"
RowSpacing="10" Padding="10">
<Grid.Resources>
<ResourceDictionary>
<Style TargetType="Frame">
<Setter Property="BackgroundColor" Value="Yellow" />
<Setter Property="OutlineColor" Value="Blue" />
</Style>
<Style TargetType="Label">
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalTextAlignment" Value="Center" />
<Setter Property="TextColor" Value="Black" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<!-- 均等分割なら、RowDefinitionsは省略可能 -->
<!--<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>-->
<Frame><Label>000</Label></Frame>
<Frame Grid.Row="1"><Label>111</Label></Frame>
<Frame Grid.Row="2"><Label>222</Label></Frame>
<Frame Grid.Row="3"><Label>333</Label></Frame>
</Grid>
</Grid>
</ContentPage>
自動生成されたLabelコントロールをコメントアウトし、<ContentPage.Padding>要素以降を追加した。
これが冒頭に示した画面のソースコードである。
なお、Gridコントロールを使うときに記述が面倒な行/列の定義であるが、Xamarin.Formsでは推論可能な行/列の定義は省略できる。
モバイル端末での実行結果は、次の画像のようになる。
実行結果
上は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のXAMLには、WPF/UWPのXAMLにはなかったレイアウト用の便利な機能がある。今回はその中から次の3点を紹介した。
- StackLayoutコントロールの子コントロールで使える「〜AndExpand」という位置指定
- GridコントロールのRowSpacingプロパティ/ColumnSpacingプロパティ
- Gridコントロールで行定義/列定義を省略できる
利用可能バージョン:Visual Studio 2015以降
カテゴリ:Xamarin 処理対象:Xamarin.Forms
関連TIPS:Xamarin.Forms:プロジェクトにXamlページを追加するには?
関連TIPS:Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?
Copyright© Digital Advantage Corp. All Rights Reserved.