WWDC Quick Look 💓 By SwiftGGTeam
Build SwiftUI apps for tvOS

Build SwiftUI apps for tvOS

元の動画を見る

ハイライト

このセッションでは、音楽アプリの例を使用して、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 アプリの共通ホームページは、複数の水平スクロール シェルフで構成されます。セッションの用途 ScrollViewLazyHGrid そして 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 カード フォーカス効果を与えます。

重要ポイント

  1. アルバム棚のホームページを作成

やるべきこと: 音楽、ビデオ、コース コンテンツを複数の水平の棚に整理し、プレイリストにまとめます。

実行する価値がある理由: ScrollView([.horizontal]) そして LazyHGrid Session によって表示されるレイアウトは、Apple TV アプリの一般的なレイアウトです。 Lazy Grid は、スクロールが必要なときに項目を読み込みます。

開始方法: 初めて使用する LazyHGrid(rows: [GridItem()]) 棚をレンダリングしてから、各カバーを Button、と追加します CardButtonStyle()

  1. コンテンツカードに長押しショートカット操作を追加

作業内容: アルバム、ビデオ、またはプレイリスト カード上の類似コンテンツの収集、作成者ページの表示、検索などのクイック アクションを提供します。

これを行う価値がある理由: セッションはアルバム ボタンを長押しすることで明示的にコンテキスト メニューを開き、メニュー項目は通常のメニューを直接使用できます。 Button

開始方法: 追加 .contextMenu カードビューの後に各アクションを次のように記述します Button("Action", action: handler)

  1. Now Playing リストをフォーカスして詳細を展開します

対処方法: 現在フォーカスされている曲にはアーティスト名とアルバム名が表示され、その他の曲にはアーティスト名のみが表示され、TV インターフェース上の情報ノイズが軽減されます。

実行する価値がある理由: isFocused これにより、各詳細ビューに個別のフォーカス ラッパーを追加することなく、サブビューがフォーカス可能な最新の祖先のフォーカス状態を読み取ることができます。

開始方法: テキスト領域を次のように分割します。 DetailsView、 読む @Environment(\.isFocused) に切り替えて、 Text ブール値に応じた内容。

  1. ログイン ページの状態主導型のデフォルト フォーカスを設定します

対処方法: 認証情報が入力されていない場合は、デフォルトでユーザー名入力ボックスがフォーカスされ、認証情報が入力されると、デフォルトでログイン ボタンがフォーカスされます。

実行する価値がある理由: tvOS はデフォルトで幾何学的位置に基づいて初期フォーカスを選択します。ログイン プロセスは、フォームのステータスに基づいてフォーカスの入り口を決定するのにより適しています。

開始方法: 作成する @Namespace、 追加 .prefersDefaultFocus ユーザー名入力ボックスとログインボタンにそれぞれ入力し、使用します .focusScope(namespace) 範囲を制限するため。

  1. フォームのクリアアクションにフォーカスリセットを追加

対処方法: ユーザーが [クリア] をクリックした後、ユーザー名とパスワードをクリアし、フォーカスをユーザー名入力ボックスに戻します。

実行する価値がある理由: セッションが明らかにする 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