ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
ウィジェットの新しい場所への展開方法
ウィジェットのエコシステムが拡大しています。最新のWidgetKit APIを使用して、ウィジェットをあらゆる場所で美しく表示する方法について解説します。ウィジェットをどんな環境にもシームレスにフィットさせるために、ウィジェットの背景を識別したり、レイアウトをダイナミックに調整したり、バイブラントレンダリングで使用するカラーを準備する方法を紹介します。
関連する章
- 0:00 - Introduction
- 1:44 - Transition to content margins
- 3:00 - Add a removable background
- 4:31 - Dynamically adjust layout
- 6:00 - Prepare for vibrant rendering
リソース
関連ビデオ
WWDC23
WWDC22
-
ダウンロード
♪ ♪
Kathryn:こんにちは System Experience エンジニアのKathrynです 本日はウィジェットの新しい表示場所と 全ての場所で優れた見た目になるように 簡単に調整する方法についてお伝えします まず ウィジェットの歴史を 簡単に解説します iOS 14でホーム画面に ウィジェットが導入され iOS 16で 同じWidgetKit APIを使って ロック画面にウィジェットが導入されました 今年 ウィジェットのエコシステムは 4カ所に拡大されます Macのデスクトップ iPadのロック画面 iPhoneの新しいスタンバイモード Apple Watchの新しいスマートスタックです これにより 人々が お気に入りのウィジェットを さらに多くの場所で見ることができます ウィジェットは これらすべての場所に 自動的に表示されるため 表示場所に関わらず 美しく見せることが大切です iPhoneのウィジェットにMacから アクセスすることもできるので macOSアプリを持っていない場合であっても Mac上で ウィジェットを使うことができます 友人のDevonとGrahamに Emoji Rangersのウィジェットを アップデートして 新しい表示場所に 対応できるように頼まれました WWDC20の「Widget Code-Along」や WWDC22の「コンプリケーションとウィジェット : リローデッド」で登場したプロジェクトです まず ウィジェットの 新しいコンテンツマージンと Apple Watchへの 移行方法について解説します 次に ウィジェットに 自動的に 削除可能な背景を追加します そして 環境に合わせて動的に レイアウトを拡大できるように ウィジェットを修正します 最後に ウィジェットの要素に対し vibrantレンダリングが 可能になるよう確認を進めます では始めましょう 今年のウィジェットの新機能は コンテンツマージンです コンテンツマージンは ウィジェットのボディに自動的に 適用される余白で コンテンツがウィジェットコンテナの端に 近づきすぎるのを防ぎます このマージンは ウィジェットが表示される 環境に応じて伸縮します watchOS 9以前では ウィジェットはシステム定義の セーフエリアを使用して コンテンツが 端に近づきすぎないようにしていました ウィジェットはignoresSafeAreaのような モディファイアをビューに追加することで セーフエリアの外側に拡張できました watchOS 10以降では ウィジェットのセーフエリアは コンテンツマージンの使用に 置き換えられます これによりignoresSafeAreaのような モディファイアは ウェジェットでは効果が無くなります ほとんどのウィジェットでは この変更は見た目に影響しません しかし ウィジェットにセーフエリアを 無視するコンテンツがある場合 contentMarginsDisabledモディファイアを 追加することで 同じ効果を得ることができます そして デフォルトのコンテンツ マージン内に残すべきコンテンツは .paddingを追加するだけでよくなります widgetContentMargins環境変数を使って 現在の環境の デフォルトマージンを取得できます コンテンツマージンはこれらの 新しいモディファイアや変数と同じく ウィジェットが表示される すべてのプラットフォームで利用可能です では Emoji Rangersウィジェットに 削除可能な背景を追加しましょう 既存のアクセサリウィジェットは iPadのロック画面でも自動的に動作します iPhoneも同様です iPadは すぐ横に システムスモール ウィジェットを表示することもできます ロック画面ではこのように表示されます この環境では 背景を削除して 他のウィジェットと合わせる必要があります 幸いなことに これはとても簡単です ここに systemSmallウィジェットの ビューのコードがあります 現在は ZStackを使って gameBackgroundカラーに AvatarViewを重ねています 背景色を削除可能にするには ビューにcontainerBackground モディファイアを追加して gameBackgroundカラーを その中に移動させます すると ウィジェットの表示場所に応じて システムが自動的に 背景を取り除くようになります Apple WatchのSmart Stackも この新しい containerBackgroundを利用できます デフォルトでは accessoryRectangularウィジェットは この環境ではダークマテリアルの背景を 受け取っています 同じcontainerBackgroundモディファイアを ビューに追加することで ウィジェットは 他のウィジェットと同じ背景に配置され アプリのビジュアル アイデンティティとリンクされます この新しい環境の詳細については 「Apple Watchのスマートスタック向け ウィジェットのデザイン」をご確認ください 写真やマップのウィジェットのように フォアグラウンドに明確なコンテンツがない ウィジェットもあります その場合 背景を削除する 意味はなくなります この場合 WidgetConfigurationに containerBackgroundRemovable モディファイアを追加して falseに設定します では iPadのロック画面や スタンバイモードでの レイアウトを最適化しましょう 天気ウィジェットは ウィジェットの背景が削除された時に レイアウトを変更する方法の例です
ウィジェットに含まれる情報は同じですが スペースを有効活用するために 最適化されています コンテンツは端まで押し出され 重要な要素は拡大されています これにより遠くからでも読みやすくなり スタンバイモードに よりシームレスに統合されます このレイアウト変更により iPadのロック画面に表示される アクセサリファミリーウィジェットと調和し どのファミリーでも 一貫した見た目を維持することができます Xcodeに移動して これらの変更を ウィジェットに実装してみましょう これは systemSmallで使用する AvatarViewのコードです 右側には Xcode Previewsで ウィジェットがどう見えるかの ライブプレビューが表示されています コンテナの背景が削除された コンテキストを表示すると widgetContentMarginsは自動的に 縮小され コンテンツが端まで表示されます showsWidgetContainerBackground 環境変数を使って ウィジェットの背景が 削除されたかを検出できます 削除された場合 ヒーローのレベルとXPの詳細を HeroNameViewで省略し 代わりにその詳細を下に表示します
この環境では ヒーローの名前も拡大されます これらのコンテンツを切り替えると レイアウトが元のビューから 新しい拡大ビューに自動で変更されます
アクセサリファミリーウィジェットと同様に システムファミリーウィジェットは iPadロック画面では vibrantレンダリング モードで表示されます つまり ウィジェットは彩度を落とし ロック画面の背景に適した色で表示されます このようにレンダリングすると コントラストが ウィジェットの読みやすさに影響します 例えば ヒーローのアバターは円形の背景と 区別が難しくなります Xcodeに戻り vibrantレンダリングモードでは 背景を削除するように ウィジェットを修正します スタンバイナイトモードで確認しましょう widgetRenderingMode環境変数を使うと 使用中のレンダリングモードを検出できます アバターのincludesBackground パラメータを変更して レンダリングモードが vibrantか確認しましょう
スタンバイナイトモードも vibrantレンダリングを使用するため アバターはこの状況でもはっきり見えます ウィジェットの レンダリングモードについては WWDC22の「コンプリケーションとウィジェット : リローデッド」をご確認ください ウィジェットのさらなる新機能については 「ウィジェットに命を吹き込む方法」を ご覧ください 今回のウィジェットの アップデートにワクワクしています ウィジェットを強化する これらの新機能を使った アイデアを楽しみにしています ありがとうございました ♪ ♪
-
-
2:08 - SafeAreasWidget
struct SafeAreasWidgetView: View { @Environment(\.widgetContentMargins) var margins var body: some View { ZStack { Color.blue Group { Color.lightBlue Text("Hello, world!") } .padding(margins) } } } struct SafeAreasWidget: Widget { var body: some WidgetConfiguration { StaticConfiguration(...) {_ in SafeAreasWidgetView() } .contentMarginsDisabled() } }
-
3:19 - EmojiRangerWidget systemSmall
struct EmojiRangerWidgetEntryView: View { var entry: Provider.Entry @Environment(\.widgetFamily) var family var body: some View { switch family { case .systemSmall: ZStack { AvatarView(entry.hero) .widgetURL(entry.hero.url) .foregroundColor(.white) } .containerBackground(for: .widget) { Color.gameBackground } } // additional cases } }
-
3:48 - EmojiRangerWidget accessoryRectangular
var body: some View { switch family { case .accessoryRectangular: HStack(alignment: .center, spacing: 0) { VStack(alignment: .leading) { Text(entry.hero.name) .font(.headline) .widgetAccentable() Text("Level \(entry.hero.level)") Text(entry.hero.fullHealthDate, style: .timer) }.frame(maxWidth: .infinity, alignment: .leading) Avatar(hero: entry.hero, includeBackground: false) } .containerBackground(for: .widget) { Color.gameBackground } // additional cases }
-
4:22 - PhotoWidget
struct PhotoWidget: Widget { public var body: some WidgetConfiguration { StaticConfiguration(...) { entry in PhotoWidgetView(entry: entry) } .containerBackgroundRemovable(false) } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。