Xamarin での tvOS スタック ビューの操作
警告
iOS Designer は、Visual Studio 2019 バージョン 16.8 および Visual Studio 2019 for Mac バージョン 8.8 で非推奨とされ、Visual Studio 2019 バージョン 16.9 および Visual Studio for Mac バージョン 8.9 から削除されています。 iOS のユーザー インターフェイスについては、Xcode の Interface Builder が実行されている Mac で直接ビルドすることをお勧めします。 詳細については、「Xcode を使用したユーザーインターフェイスの設計」を参照してください。
スタック ビュー コントロール (UIStackView
) は、自動レイアウト クラスとサイズ クラスの機能を利用して、Apple TV デバイスのコンテンツ変更と画面サイズに動的に対応するサブビューのスタック (水平方向または垂直方向) を管理します。
スタック ビューにアタッチされているすべてのサブビューのレイアウトは、軸、分布、配置、間隔などの開発者が定義したプロパティに基づいてスタック ビューによって管理されます。
Xamarin.tvOS アプリで UIStackView
を使用する場合、開発者は、iOS Designer のストーリーボード内で、または C# コードでサブビューを追加および削除することで、サブビューを定義できます。
スタック ビュー コントロールについて
UIStackView
は、非レンダリング コンテナー ビューとして設計されているため、UIView
のその他のサブクラスのようにはキャンバスに描画されません。 BackgroundColor
などのプロパティを設定しても、DrawRect
をオーバーライドしても、視覚的な効果はありません。
スタック ビューでサブビューのコレクションを配置する方法を制御するプロパティがいくつかあります。
- 軸 – スタック ビューによってサブビューが水平方向または垂直方向に配置されるかどうかを決定します。
- 配置 – スタック ビュー内でのサブビューの配置方法を制御します。
- 分布 – スタック ビュー内でサブビューのサイズを設定する方法を制御します。
- 間隔 – スタック ビュー内の各サブビュー間の最小スペースを制御します。
- ベースライン基準 –
true
である場合、各サブビューの垂直方向の間隔は、そのベースラインから派生します。 - レイアウト余白基準 – 標準レイアウトの余白を基準にサブビューを配置します。
通常、スタック ビューを使用して、少数のサブビューを配置します。 1 つ以上のスタック ビューを相互に入れ子にすることで、より複雑なユーザー インターフェイスを作成できます。
サブビューに制約を追加することで、UI の外観をさらに微調整できます (たとえば、高さや幅を制御できます)。 ただし、スタック ビュー自体によって導入されたサブビューに競合する制約を含めないように注意する必要があります。
自動レイアウト クラスとサイズ クラス
サブビューをスタック ビューに追加すると、配置されたビューを配置およびサイズ変更するために、そのレイアウトが自動レイアウト クラスとサイズ クラスを使用してスタック ビューによって完全に制御されます。
スタック ビューでは、コレクション内の最初と最後のサブビューが、垂直スタック ビューの場合は上端と下端、水平スタック ビューの場合は左端と右端にピン留めされます。 LayoutMarginsRelativeArrangement
プロパティを true
に設定すると、サブビューは端ではなく、関連する余白にピン留めされます。
スタック ビューでは、定義された Axis
に沿ったサブビューのサイズを計算するときにサブビューの IntrinsicContentSize
プロパティが使用されます (FillEqually Distribution
は除きます)。 FillEqually Distribution
の場合、すべてのサブビューのサイズが同じになるようにサイズが変更され、これにより、Axis
に沿ってスタック ビューが塗りつぶされます。
Fill Alignment
を除き、スタック ビューでは、指定された Axis
ビューに対して垂直なビューのサイズを計算するためにサブビューの IntrinsicContentSize
プロパティが使用されます。 Fill Alignment
の場合、すべてのサブビューによって指定されたAxis
に対して垂直なスタック ビューが塗りつぶされるように、これらのサブビューのサイズが設定されます。
スタック ビューの配置とサイズ設定
サブビューのレイアウトは (Axis
や Distribution
などのプロパティに基づいて) スタック ビューによって完全に制御されますが、ユーザーは依然として、自動レイアウト クラスとサイズ クラスを使用して親ビュー内にスタック ビュー (UIStackView
) を配置する必要があります。
一般に、これは、スタック ビューの少なくとも 2 つの端をピン留めして拡大および縮小し、その位置を定義することを意味します。 追加の制約がない場合、スタック ビューは次のように、すべてのサブビューをサイズに合わせて調整するために自動的にサイズ変更されます。
Axis
に沿ったサイズは、すべてのサブビューのサイズの合計に、各サブビュー間で定義されたスペースを足した値になります。LayoutMarginsRelativeArrangement
プロパティがtrue
である場合、スタック ビューのサイズには余白のスペースも含まれます。Axis
に対して垂直なサイズは、コレクション内の最大サブビューに設定されます。
また、スタック ビューの高さと幅の制約を指定することもできます。 この場合、サブビューは、Distribution
および Alignment
プロパティによって決定されたとおりにスタック ビューによって指定されたスペースを塗りつぶすようにレイアウト (サイズ設定) されます。
BaselineRelativeArrangement
プロパティが true
である場合、サブビューは、上、下、または中心 - Y の位置ではなく、最初または最後のサブビューのベースラインに基づいてレイアウトされます。 これらは、次のようにスタック ビューのコンテンツで計算されます。
- 垂直スタック ビューにより、最初のベースラインに対して最初のサブビュー、および最後のベースラインに対して最後のサブビューが返されます。 これらのいずれかのサブビュー自体がスタック ビューである場合は、最初または最後のベースラインが使用されます。
- 水平スタック ビューにより、最初のベースラインと最後のベースラインの両方に対して最も高いサブビューが使用されます。 最も高いビューがスタック ビューでもある場合は、最も高いサブビューがベースラインとして使用されます。
重要
ベースラインの配置は、拡大または圧縮されたサブビューのサイズに対しては機能しません。なぜなら、ベースラインの計算結果が間違った位置になるからです。 ベースライン配置の場合、サブビューの高さが組み込みコンテンツ ビューの高さと一致していることを確認します。
一般的なスタック ビューの用途
スタック ビュー コントロールで適切に動作するレイアウトの種類がいくつかあります。 Apple によると、いくつかの一般的な用途には次のものがあります。
- 軸に沿ったサイズの定義 – スタック ビューの
Axis
に沿って両方の端をピン留めし、隣接する端の 1 つを固定して位置を設定することで、サブビューで定義されたスペースに合うようにスタック ビューが軸に沿って拡大されます。 - サブビューの位置の定義 – スタック ビューの隣接する端を親ビューにピン留めすることで、スタック ビューは、含まれるサブビューに合うように両方向に拡大されます。
- スタック ビューのサイズと位置の定義 – スタック ビューの4つの端をすべて親ビューにピン留めすることで、スタック ビューによってスタック ビュー内で定義されたスペースに基づいてサブビューが配置されます。
- 軸に垂直なサイズの定義 – スタック ビューの
Axis
に垂直な両方の端と、軸に沿った端の 1 つエッジをピン留めして位置を設定することで、スタック ビューはサブビューで定義されたスペースに合わせて軸に垂直に拡大されます。
スタック ビューとストーリーボード
Xamarin.tvOS アプリでスタック ビューを操作する最も簡単な方法は、iOS Designer を使用してアプリの UI に追加することです。
Solution Pad で
Main.storyboard
ファイルをダブルクリックして、編集用に開きます。スタック ビューに追加する個々の要素のレイアウトを設計します。
要素が正しくスケーリングされるように、要素に必要な制約を追加します。 この手順は、要素がスタック ビューに追加された後に重要になります。
必要な数のコピーを作成します (この場合は 4 つ)。
ツールボックスからスタック ビューをドラッグし、ビューにドロップします。
スタック ビューを選択し、Properties Pad の [ウィジェット] タブで、[配置] に [塗りつぶし] を選択し、[分布] に [均等に塗りつぶし] を選択し、[間隔] に「
25
」と入力します。スタック ビューを画面の目的の場所に配置し、必要な場所に保持するために制約を追加します。
個々の要素を選択し、スタック ビューにドラッグします。
レイアウトが調整され、上記で設定した属性に基づいてスタック ビューに要素が配置されます。
C# コードで UI コントロールを操作するために、Properties Explorer の [ウィジェット] タブに [名前] を割り当てます。
変更を保存します。
重要
イベント ハンドラーの作成時に iOS Designer で TouchUpInside
などのアクションを UI 要素 (UIButton
など) に割り当てることは可能ですが、Apple TV にはタッチ スクリーンがないか、タッチ イベントをサポートしていないため、このアクションが呼び出されることはありません。 tvOS ユーザー インターフェイス要素のアクションを作成する場合は、常に既定の Action Type
を使用する必要があります。
ストーリーボードの使用の詳細については、「はじめての tvOS クイック スタート ガイド」を参照してください。
この例では、セグメント コントロールに対してアウトレットとアクションを、"プレイヤー カード" ごとにアウトレットを公開しました。 コードでは、現在のセグメントに基づいてプレーヤーの非表示と表示を切り替えます。 次に例を示します。
partial void PlayerCountChanged (Foundation.NSObject sender) {
// Take Action based on the segment
switch(PlayerCount.SelectedSegment) {
case 0:
Player1.Hidden = false;
Player2.Hidden = true;
Player3.Hidden = true;
Player4.Hidden = true;
break;
case 1:
Player1.Hidden = false;
Player2.Hidden = false;
Player3.Hidden = true;
Player4.Hidden = true;
break;
case 2:
Player1.Hidden = false;
Player2.Hidden = false;
Player3.Hidden = false;
Player4.Hidden = true;
break;
case 3:
Player1.Hidden = false;
Player2.Hidden = false;
Player3.Hidden = false;
Player4.Hidden = false;
break;
}
}
アプリを実行すると、スタック ビューで4 つの要素が均等に分散されます。
プレイヤーの数が減ると、未使用のビューは非表示になり、スタック ビューによってレイアウトがサイズに合わせて調整されます。
コードからのスタック ビューの設定
iOS Designer でスタック ビューのコンテンツとレイアウトを完全に定義するだけでなく、C# コードから動的に作成および削除することもできます。
次の例では、スタック ビューを使用してレビューの "星" (stars) を処理します (1 から 5)。
public int Rating { get; set;} = 0;
...
partial void IncreaseRating (Foundation.NSObject sender) {
// Maximum of 5 "stars"
if (++Rating > 5 ) {
// Abort
Rating = 5;
return;
}
// Create new rating icon and add it to stack
var icon = new UIImageView (new UIImage("icon.png"));
icon.ContentMode = UIViewContentMode.ScaleAspectFit;
RatingView.AddArrangedSubview(icon);
// Animate stack
UIView.Animate(0.25, ()=>{
// Adjust stack view
RatingView.LayoutIfNeeded();
});
}
partial void DecreaseRating (Foundation.NSObject sender) {
// Minimum of zero "stars"
if (--Rating < 0) {
// Abort
Rating =0;
return;
}
// Get the last subview added
var icon = RatingView.ArrangedSubviews[RatingView.ArrangedSubviews.Length-1];
// Remove from stack and screen
RatingView.RemoveArrangedSubview(icon);
icon.RemoveFromSuperview();
// Animate stack
UIView.Animate(0.25, ()=>{
// Adjust stack view
RatingView.LayoutIfNeeded();
});
}
このコードのいくつかの部分を詳しく見てみましょう。 まず、if
ステートメントを使用して、"星" の数が 5 より大きくないか、または 0 より小さくないかを確認します。
新しい "星" を追加するには、そのイメージを読み込み、Content Mode を Scale Aspect Fit に設定します。
var icon = new UIImageView (new UIImage("icon.png"));
icon.ContentMode = UIViewContentMode.ScaleAspectFit;
これにより、"星" アイコンがスタック ビューに追加されたときに歪むことを防止できます。
次に、新しい "星" アイコンをスタック ビューのサブビューのコレクションに追加します。
RatingView.AddArrangedSubview(icon);
UIImageView
を UIStackView
の SubView
ではなく ArrangedSubviews
プロパティに追加したことに注意してください。 スタック ビューでレイアウトを制御するビューは、ArrangedSubviews
プロパティに追加する必要があります。
スタック ビューからサブビューを削除するには、まず、削除するサブビューを取得します。
var icon = RatingView.ArrangedSubviews[RatingView.ArrangedSubviews.Length-1];
次に、それを ArrangedSubviews
コレクションとスーパー ビューの両方から削除する必要があります。
// Remove from stack and screen
RatingView.RemoveArrangedSubview(icon);
icon.RemoveFromSuperview();
ArrangedSubviews
コレクションだけからサブビューを削除した場合、スタック ビューのコントロールからは外れますが、画面からは削除されません。
コンテンツの動的変更
スタック ビューでは、サブビューが追加、削除、または非表示になるたびに、サブビューのレイアウトが自動的に調整されます。 スタック ビューのいずれかのプロパティ (Axis
など) を調整すると、レイアウトも調整されます。
レイアウトの変更は、アニメーション ブロック内に配置することでアニメーション化できます。次に例を示します。
// Animate stack
UIView.Animate(0.25, ()=>{
// Adjust stack view
RatingView.LayoutIfNeeded();
});
スタック ビューのプロパティの多くは、ストーリーボード内のサイズ クラスを使用して指定できます。 これらのプロパティは、サイズや向きの変更に応じて自動的にアニメーション化されます。
まとめ
この記事では、Xamarin.tvOS アプリ内でのスタック ビューの設計と使用について説明しました。