ハイライト
このセッションでは、音楽アプリの例を使用して、tvOS 14 の SwiftUI ボタン スタイル、コンテキスト メニュー、フォーカス API、Lazy Grid をデモンストレーションし、Apple TV アプリでリモコンのフォーカス、長押し操作、および水平シェルフ レイアウトを処理できるようにします。
主要内容
iPhone や iPad の SwiftUI のアイデアを TV に移す場合、最初の違いは入力方法です。 Apple TV ユーザーは、Siri Remote を使用してフォーカスを移動したり、ボタンを押し続けたり、遠くから大画面インターフェイスを表示したりできます。音楽アプリのアルバムボタンを通常のボタンにしただけでは、リモコンをドラッグした際のフォーカスハイライトや方向移動効果が不足します。
このセッションでは、音楽アプリを使用して 3 つの問題を結び付けます。アルバム カードには TV スタイルのボタンと長押しメニューが必要です。 Now Playing ページでは、どの曲がフォーカスされているかを知る必要があります。また、ログイン ページでは、ユーザー名入力ボックスとログイン ボタンの間のデフォルトのフォーカスを制御する必要があります。すべての例は、tvOS 14 の SwiftUI API を中心に展開しています。
最後の問題はレイアウトです。 Apple TV アプリの共通ホームページは、複数の水平スクロール シェルフで構成されます。セッションの用途 ScrollView、 LazyHGrid そして CardButtonStyle このレイアウトを組み合わせて、スクロールが必要なときに Lazy Grid が項目をロードすることを説明します。
詳細
TV スタイルのボタンと長押しメニュー
(01:19) CardButtonStyle 大皿を作成します。ボタンにフォーカスがあると、プラッターが持ち上がってハイライト表示されます。ユーザーが Siri リモート上でドラッグすると、ボタンがその方向に移動します。
Button(albumLabel, action: playAlbum)
.buttonStyle(CardButtonStyle())
キーポイント:
Button(albumLabel, action: playAlbum)はアルバム エントリであり、ユーザーが選択した後に再生アクションが実行されます。.buttonStyle(CardButtonStyle())通常の SwiftUI ボタンを tvOS カード ボタン スタイルに置き換えます。- このスタイルは、ボタンの外側に手書きのアニメーションを必要とせずに、フォーカスの強調表示とリモート コントロールのドラッグ フィードバックを担当します。
(02:20) デフォルトのハイライト効果とフォーカス効果が適切でない場合は、カスタマイズできます。 ButtonStyle。セッション コードは構造を表示するだけであり、特定の背景スタイルはアプリ自体によって完成されます。
struct MyNewButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(configuration.isPressed ? … : …) // Custom styling
}
}
Button(albumLabel, action: playAlbum)
.buttonStyle(MyNewButtonStyle())
キーポイント:
MyNewButtonStyleに準拠しますButtonStyleプロトコル。makeBody(configuration:)さまざまな状態のボタンのビューを返します。configuration.isPressedはボタンの状態から取得され、押されたときに背景を切り替えるために使用できます。.buttonStyle(MyNewButtonStyle())同じスタイルを任意のボタンに再利用できます。
(03:04) アルバムボタンを長押ししてコンテキストメニューを開きます。メニュー項目は通常どおり表示されます Button。
AlbumView()
.contextMenu {
Button("Add to Favorites", action: addAlbumToFavorites)
Button("View Artist", action: viewArtistPage)
Button("Discover Similar Albums", action: viewSimilarAlbums)
}
キーポイント:
AlbumView()メニューマウントのターゲットビューです。.contextMenu長押し後に表示されるショートカット操作領域を宣言します。- それぞれ
Buttonはメニュー アクションで、それぞれコレクションへの接続、アーティスト ページの表示、類似アルバムの検出を行います。
フォーカス状態に応じてコンテンツ密度を変更する
(05:19) tvOS 14 には新しい機能が追加されています isFocused 環境価値。戻ります true 最も近いフォーカス可能な祖先にフォーカスがあるとき。 [再生中のセッション] ページの説明: フォーカスされている曲の場合はアーティスト名とアルバム名が表示され、フォーカスされていない曲の場合はアーティスト名のみが表示されます。
struct SongView: View {
var body: some View {
Button(action: playSong) {
VStack {
Image(albumArt)
DetailsView(...)
}
}.buttonStyle(MyCustomButtonStyle())
}
}
struct DetailsView: View {
...
@Environment(\.isFocused) var isFocused: Bool
var body: some View {
VStack {
Text(songName)
Text(isFocused ? artistAndAlbum : artistName)
}
}
}
キーポイント:
SongView用途Button、ボタン自体はフォーカス可能です。DetailsView読む@Environment(\.isFocused)それ自体をフォーカス可能なビューにすることはありません。Text(isFocused ? artistAndAlbum : artistName)フォーカス状態に応じて表示情報を切り替えます。- セッションは、UIKit によってフォーカスが管理されているボタン、リスト、ビューはオーバーレイには適していないことを明確に思い出させます。
focusable修飾子。
デフォルトのフォーカスを制御し、状態変更後にリセットする
(08:01) tvOS は初期フォーカスを幾何学的に計算し、通常は画面の上部または最前面のフォーカス可能なビューに当てられます。ログイン ページがデフォルトでユーザー名入力ボックスに重点を置くのは合理的です。ユーザー名とパスワードが入力されている場合、デフォルトのフォーカスはログイン ボタンに置かれます。
@Namespace private var namespace
@State private var areCredentialsFilled: Bool
var body: some View {
VStack {
TextField("Username", text: $username)
.prefersDefaultFocus(!areCredentialsFilled, in: namespace)
SecureField("Password", text: $password)
Button("Log In", action: logIn)
.prefersDefaultFocus(areCredentialsFilled, in: namespace)
}
.focusScope(namespace)
}
キーポイント:
@Namespace private var namespaceフォーカス範囲を識別するために使用される一意の ID を作成します。areCredentialsFilledユーザー名入力ボックスとログイン ボタンのどちらがデフォルトのフォーカスとして適しているかを決定します。.prefersDefaultFocus(..., in: namespace)は好みを表現するだけであり、グローバル フォーカス ツリーを直接操作するものではありません。.focusScope(namespace)これらの設定を現在のものに制限しますVStack。
(10:35) ログインフォームをクリアした後、フォーカスをデフォルトの位置に戻す必要があります。の resetFocus 環境アクションは、同じ名前空間によってフォーカスをリセットします。
@Namespace private var namespace
@State private var areCredentialsFilled: Bool
@Environment(\.resetFocus) var resetFocus
var body: some View {
VStack {
TextField("Username", text: $username)
.prefersDefaultFocus(!areCredentialsFilled, in: namespace)
SecureField("Password", text: $password)
Button("Log In", action: logIn)
.prefersDefaultFocus(areCredentialsFilled, in: namespace)
Button("Clear", action: {
username = ""; password = ""
areCredentialsFilled = false
resetFocus(in: namespace)
})
}
.focusScope(namespace)
}
キーポイント:
@Environment(\.resetFocus)システムによって提供されるリセット フォーカス アクションを取り除きます。- クリアボタンを押すとクリアされます
usernameそしてpassword初め。 areCredentialsFilled = falseユーザー名入力ボックスにデフォルトのフォーカス設定を再設定します。resetFocus(in: namespace)現在のフォーカス スコープ内でのみリセットを実行します。
Lazy Grid を使用して TV ホームページの棚を整理する
(12:08) Apple TV アプリの一般的な水平シェルフ レイアウトは、Lazy Grid を使用して実装できます。 Lazy Grid はオンデマンドで項目を初期化し、水平スクロール領域に多数のカバーを配置するのに適しています。
struct ShelfView: View {
var body: some View {
ScrollView([.horizontal]) {
LazyHGrid(rows: [GridItem()]) {
ForEach(playlists, id: \.self) { playlist in
Button(action: goToPlaylist) {
Image(playlist.coverImage)
.resizable()
.frame(…)
}
.buttonStyle(CardButtonStyle())
}
}
}
}
}
キーポイント:
ScrollView([.horizontal])水平スクロール領域を作成します。LazyHGrid(rows: [GridItem()])水平棚をグリッド列で整理します。ForEach(playlists, id: \.self)プレイリストをカバーボタンに 1 つずつマップします。Image(playlist.coverImage).resizable().frame(…)は、カバーのサイズが変更可能であり、サイズはアプリによって指定されることを意味します。.buttonStyle(CardButtonStyle())各カバー ボタンに tvOS カード フォーカス効果を与えます。
重要ポイント
- アルバム棚のホームページを作成
やるべきこと: 音楽、ビデオ、コース コンテンツを複数の水平の棚に整理し、プレイリストにまとめます。
実行する価値がある理由: ScrollView([.horizontal]) そして LazyHGrid Session によって表示されるレイアウトは、Apple TV アプリの一般的なレイアウトです。 Lazy Grid は、スクロールが必要なときに項目を読み込みます。
開始方法: 初めて使用する LazyHGrid(rows: [GridItem()]) 棚をレンダリングしてから、各カバーを Button、と追加します CardButtonStyle()。
- コンテンツカードに長押しショートカット操作を追加
作業内容: アルバム、ビデオ、またはプレイリスト カード上の類似コンテンツの収集、作成者ページの表示、検索などのクイック アクションを提供します。
これを行う価値がある理由: セッションはアルバム ボタンを長押しすることで明示的にコンテキスト メニューを開き、メニュー項目は通常のメニューを直接使用できます。 Button。
開始方法: 追加 .contextMenu カードビューの後に各アクションを次のように記述します Button("Action", action: handler)。
- Now Playing リストをフォーカスして詳細を展開します
対処方法: 現在フォーカスされている曲にはアーティスト名とアルバム名が表示され、その他の曲にはアーティスト名のみが表示され、TV インターフェース上の情報ノイズが軽減されます。
実行する価値がある理由: isFocused これにより、各詳細ビューに個別のフォーカス ラッパーを追加することなく、サブビューがフォーカス可能な最新の祖先のフォーカス状態を読み取ることができます。
開始方法: テキスト領域を次のように分割します。 DetailsView、 読む @Environment(\.isFocused) に切り替えて、 Text ブール値に応じた内容。
- ログイン ページの状態主導型のデフォルト フォーカスを設定します
対処方法: 認証情報が入力されていない場合は、デフォルトでユーザー名入力ボックスがフォーカスされ、認証情報が入力されると、デフォルトでログイン ボタンがフォーカスされます。
実行する価値がある理由: tvOS はデフォルトで幾何学的位置に基づいて初期フォーカスを選択します。ログイン プロセスは、フォームのステータスに基づいてフォーカスの入り口を決定するのにより適しています。
開始方法: 作成する @Namespace、 追加 .prefersDefaultFocus ユーザー名入力ボックスとログインボタンにそれぞれ入力し、使用します .focusScope(namespace) 範囲を制限するため。
- フォームのクリアアクションにフォーカスリセットを追加
対処方法: ユーザーが [クリア] をクリックした後、ユーザー名とパスワードをクリアし、フォーカスをユーザー名入力ボックスに戻します。
実行する価値がある理由: セッションが明らかにする resetFocus(in:)、現在の名前空間のデフォルト設定に従ってフォーカスを再計算します。
開始方法: 読む @Environment(\.resetFocus)、[クリア]ボタン アクションでフォームのステータスを更新してから、呼び出します。 resetFocus(in: namespace)。
関連セッション
- SwiftUI の新機能 — iPhone、iPad、Mac、Apple Watch、Apple TV の SwiftUI の年次更新について説明します。
- SwiftUI のスタック、グリッド、およびアウトライン - このセッションのシェルフ レイアウトのすぐ隣に、Lazy Grid、リストおよびアウトライン関連のレイアウト機能を追加しました。
- SwiftUI のアプリの要点 — アプリ、シーン、ビューが完全な SwiftUI アプリを形成する方法について説明します。これは、tvOS SwiftUI アプリの構造的なフロントエンドとして適しています。
- tvOS のマスター ピクチャー イン ピクチャー — これは同じ tvOS エクスペリエンスのテーマに属しており、フルスクリーン コンテンツとピクチャー イン ピクチャーの間の切り替えについて説明しています。
- Apple TV の検索候補を見つける — これは Apple TV アプリ エクスペリエンスのテーマにも属しており、tvOS 検索インターフェイスと
UISearchController。
コメント
GitHub Issues · utterances