【My Netaflix画面】プロフィール・通知・ダウンロード・視聴中リストを表示する
この節で学ぶこと
前の節では、検索結果UIを作りました。
検索結果があるときは作品一覧を表示し、見つからないときは EmptySearchResult を表示することで、検索画面として自然な動きを作りました。
今回の節では、BottomNavigationの最後のタブである My Netaflix画面 を作ります。
My Netaflix画面は、ユーザー自身の情報や、通知、ダウンロード、視聴中リスト、My Listなどをまとめて表示する画面です。
My Netaflix画面
↓
プロフィール画像を表示
↓
通知・ダウンロードのメニューを表示
↓
視聴中リストを表示
↓
My Listを表示
動画アプリでは、Home、Search、Clipsだけでなく、「自分のページ」があることで、アプリ全体の完成度が高く見えます。
この節では、プロフィール画面らしいUIを、MyNetflixPage と MyNetflixCard を使って作っていきます。
My Netaflix画面の完成イメージ
今回作る画面は、次のような構成です。
┌────────────────────┐
│ My Netaflix │
│ ✎ │
│ │
│ [プロフィール画像] │
│ User │
│ │
│ ┌────────────────┐ │
│ │ 🔔 Notifications│ │
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ ↓ Downloads │ │
│ └────────────────┘ │
│ │
│ Continue Watching │
│ [作品] [作品] [作品] │
│ │
│ My List │
│ [作品] [作品] [作品] │
└────────────────────┘
画面上部にはタイトルと編集アイコンを置きます。
中央にはプロフィール画像と名前を置きます。
その下に、通知やダウンロードなどのメニューカードを置きます。
さらに下に、視聴中の作品リストやMy Listを表示します。
今回見るコード
今回中心になるWidgetは、次の2つです。
MyNetflixPage
MyNetflixCard
役割は次の通りです。
| Widget | 役割 |
|---|---|
MyNetflixPage | My Netaflix画面全体を作る |
MyNetflixCard | 通知・ダウンロードなどのメニューカードを作る |
まずは、MyNetflixPage 全体のコードを見ていきます。
class MyNetflixPage extends StatelessWidget {
const MyNetflixPage({super.key});
@override
Widget build(BuildContext context) {
final watchingMovies = movies.take(4).toList();
final myListMovies = movies.skip(2).take(4).toList();
return Scaffold(
backgroundColor: NetflixColors.black,
body: SafeArea(
child: ListView(
padding: const EdgeInsets.fromLTRB(18, 18, 18, 110),
children: [
Row(
children: [
const Text(
'My Netaflix',
style: TextStyle(
color: NetflixColors.white,
fontSize: 28,
fontWeight: FontWeight.w900,
),
),
const Spacer(),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit_outlined,
color: NetflixColors.white,
),
),
],
),
const SizedBox(height: 24),
Center(
child: Column(
children: [
CircleAvatar(
radius: 44,
backgroundImage: NetworkImage(profileImageUrl),
),
const SizedBox(height: 10),
const Text(
'Netaflix User',
style: TextStyle(
color: NetflixColors.white,
fontSize: 17,
fontWeight: FontWeight.w800,
),
),
],
),
),
const SizedBox(height: 28),
const MyNetflixCard(
icon: Icons.notifications_none_rounded,
title: 'Notifications',
subtitle: 'Check your latest updates',
),
const SizedBox(height: 12),
const MyNetflixCard(
icon: Icons.file_download_outlined,
title: 'Downloads',
subtitle: 'Watch your saved titles offline',
),
const SizedBox(height: 28),
RowTitle(title: 'Continue Watching'),
const SizedBox(height: 12),
ContentRow(items: watchingMovies),
const SizedBox(height: 28),
RowTitle(title: 'My List'),
const SizedBox(height: 12),
ContentRow(items: myListMovies),
],
),
),
);
}
}
このコードは少し長く見えますが、構造はシンプルです。
Scaffold
↓
SafeArea
↓
ListView
↓
タイトル行
↓
プロフィール
↓
メニューカード
↓
視聴中リスト
↓
My List
MyNetflixPageはStatelessWidgetで作る
MyNetflixPage は、StatelessWidget で作っています。
class MyNetflixPage extends StatelessWidget {
const MyNetflixPage({super.key});
StatelessWidget は、内部で状態を持たないWidgetです。
今回のMy Netaflix画面では、検索欄のように入力によって変わる状態はありません。
LikeボタンのON/OFFのような状態も、この画面内では管理していません。
そのため、StatelessWidget で十分です。
画面内で状態を変更しない
↓
StatelessWidgetでよい
watchingMoviesとmyListMoviesを作る
build メソッドの最初で、2つの作品リストを作っています。
final watchingMovies = movies.take(4).toList();
final myListMovies = movies.skip(2).take(4).toList();
この2つは、画面下部に表示する作品リストです。
| 変数 | 役割 |
|---|---|
watchingMovies | 視聴中リストに表示する作品 |
myListMovies | My Listに表示する作品 |
本格的なアプリでは、ユーザーごとの視聴履歴や保存リストをデータベースから取得します。
しかし、今回は教材用なので、すでに用意している movies から一部を取り出して表示しています。
takeで先頭から作品を取り出す
まず、watchingMovies を見てみましょう。
final watchingMovies = movies.take(4).toList();
take(4) は、リストの先頭から4件を取り出す処理です。
movies = [A, B, C, D, E, F]
↓
movies.take(4)
↓
[A, B, C, D]
take の結果はそのままだと Iterable なので、toList() を使って List に変換しています。
.toList()
今回の ContentRow は List<MovieItem> を受け取る想定なので、toList() をつけています。
skipで途中から作品を取り出す
次に、myListMovies を見てみましょう。
final myListMovies = movies.skip(2).take(4).toList();
skip(2) は、先頭から2件を飛ばす処理です。
movies = [A, B, C, D, E, F]
↓
movies.skip(2)
↓
[C, D, E, F]
そこからさらに take(4) で4件を取り出しています。
movies.skip(2).take(4)
↓
[C, D, E, F]
このようにすると、Continue Watching と My List で少し違う作品を表示できます。
takeとskipを使う理由
教材用アプリでは、まだ本物のログイン機能や保存機能を作っていません。
そのため、ユーザーごとの視聴履歴やMy Listは、実際には存在しません。
そこで、仮のデータとして movies から一部を取り出しています。
本格的なアプリ
↓
データベースから視聴履歴を取得
今回の教材
↓
moviesから一部を取り出して表示
このようにしておくと、見た目は本物のアプリらしくなります。
あとでログイン機能や保存機能を追加するときにも、表示部分の考え方はそのまま使えます。
Scaffoldで画面の土台を作る
My Netaflix画面全体は、Scaffold で作っています。
return Scaffold(
backgroundColor: NetflixColors.black,
body: SafeArea(
child: ListView(
...
),
),
);
Scaffold は、Flutterで画面の土台を作るためのWidgetです。
今回は、背景色を黒にしています。
backgroundColor: NetflixColors.black,
Netflix風の画面なので、全体を黒背景にしています。
SafeAreaで端末の余白を守る
Scaffold の中では、SafeArea を使っています。
body: SafeArea(
child: ListView(
...
),
),
SafeArea は、スマホのノッチ、ステータスバー、ホームインジケーターなどにUIが重ならないようにするWidgetです。
ステータスバー
ノッチ
ホームインジケーター
↓
UIが重ならないようにする
My Netaflix画面は、上にタイトル、下にリストがあるため、画面端に近いUIが多くなります。
そのため、SafeArea で包んでおくと安心です。
ListViewで縦スクロールできる画面にする
My Netaflix画面の中身は、ListView で作っています。
ListView(
padding: const EdgeInsets.fromLTRB(18, 18, 18, 110),
children: [
...
],
)
ListView を使うと、画面の内容が多くなったときに縦スクロールできます。
今回のMy Netaflix画面には、プロフィール、メニューカード、作品リストが入ります。
スマホの画面サイズによっては、すべてが一画面に収まらない場合があります。
内容が多い
↓
一画面に収まらない
↓
ListViewでスクロールできるようにする
paddingで画面全体の余白を作る
ListView には、画面全体の余白を指定しています。
padding: const EdgeInsets.fromLTRB(18, 18, 18, 110),
これは、左・上・右・下の余白を表します。
| 位置 | 余白 |
|---|---|
| 左 | 18 |
| 上 | 18 |
| 右 | 18 |
| 下 | 110 |
下の余白が大きい理由は、BottomNavigationと重ならないようにするためです。
画面下部
↓
BottomNavigationがある
↓
最後のコンテンツが隠れないように下余白を大きくする
アプリで下部ナビゲーションを使うときは、下の余白を忘れないようにしましょう。
上部タイトル行を作る
My Netaflix画面の一番上には、タイトル行があります。
Row(
children: [
const Text(
'My Netaflix',
style: TextStyle(
color: NetflixColors.white,
fontSize: 28,
fontWeight: FontWeight.w900,
),
),
const Spacer(),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit_outlined,
color: NetflixColors.white,
),
),
],
),
左に My Netaflix、右に編集アイコンを置いています。
My Netaflix 編集アイコン
横並びなので、Row を使います。
Rowで横並びにする
Row は、子Widgetを横方向に並べるためのWidgetです。
Row(
children: [
Text(...),
Spacer(),
IconButton(...),
],
)
今回のように、左にタイトル、右にアイコンを置きたい場合に使います。
左側:タイトル
右側:アイコン
Column が縦並び、Row が横並びと覚えておくと分かりやすいです。
Textで画面タイトルを表示する
タイトルは、Text で表示しています。
const Text(
'My Netaflix',
style: TextStyle(
color: NetflixColors.white,
fontSize: 28,
fontWeight: FontWeight.w900,
),
),
黒背景なので、文字色は白です。
color: NetflixColors.white,
タイトルなので、文字サイズは大きめの 28 にしています。
fontSize: 28,
太さも強めにしています。
fontWeight: FontWeight.w900,
画面の見出しは、他の文字よりも大きく・太くすると、画面構造が分かりやすくなります。
Spacerでタイトルとアイコンを左右に分ける
タイトルとアイコンの間には、Spacer があります。
const Spacer(),
Spacer は、空いているスペースを埋めるWidgetです。
これにより、タイトルは左に、編集アイコンは右に配置されます。
タイトル 空白 編集アイコン
Row の中で左右に分けたいときに、Spacer はとてもよく使います。
IconButtonで編集アイコンを置く
右側には、IconButton を置いています。
IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit_outlined,
color: NetflixColors.white,
),
),
IconButton は、アイコンをボタンとして使うWidgetです。
ここでは、編集を表すアイコンを置いています。
Icons.edit_outlined
今回は、まだ編集機能は実装していません。
そのため、onPressed は空にしています。
onPressed: () {},
本格的に作る場合は、プロフィール編集画面へ移動する処理を入れます。
SizedBoxでタイトル下に余白を作る
タイトル行の下には、余白を入れています。
const SizedBox(height: 24),
SizedBox は、決まった大きさの空間を作るWidgetです。
タイトルのすぐ下にプロフィール画像が来ると、少し詰まって見えます。
タイトル
プロフィール画像
余白を入れると、見やすくなります。
タイトル
プロフィール画像
画面デザインでは、このような余白がとても大切です。
プロフィール部分を中央に配置する
プロフィール部分は、Center と Column で作っています。
Center(
child: Column(
children: [
CircleAvatar(
radius: 44,
backgroundImage: NetworkImage(profileImageUrl),
),
const SizedBox(height: 10),
const Text(
'Netaflix User',
style: TextStyle(
color: NetflixColors.white,
fontSize: 17,
fontWeight: FontWeight.w800,
),
),
],
),
),
Center を使うことで、プロフィール画像と名前を画面中央に置いています。
プロフィール画像
User名
Myページでは、ユーザー自身の情報が中心になるので、中央配置にすると分かりやすくなります。
CircleAvatarでプロフィール画像を表示する
プロフィール画像は、CircleAvatar で表示しています。
CircleAvatar(
radius: 44,
backgroundImage: NetworkImage(profileImageUrl),
),
CircleAvatar は、丸いプロフィール画像を表示するためによく使われるWidgetです。
SNSやアカウント画面では、丸いアイコンがよく使われます。
丸いプロフィール画像
今回の画面でも、アカウント画面らしさを出すために CircleAvatar を使っています。
radiusでプロフィール画像の大きさを決める
CircleAvatar の大きさは、radius で決めています。
radius: 44,
radius は半径です。
つまり、直径は約88になります。
半径 44
↓
直径 88
大きすぎると画面を圧迫します。
小さすぎるとプロフィールらしさが弱くなります。
Myページの中央に置くプロフィール画像としては、ほどよいサイズです。
NetworkImageで画像URLを読み込む
プロフィール画像には、NetworkImage を使っています。
backgroundImage: NetworkImage(profileImageUrl),
profileImageUrl には、プロフィール画像のURLが入っています。
profileImageUrl
NetworkImage を使うと、インターネット上の画像を読み込んで表示できます。
画像URL
↓
NetworkImage
↓
CircleAvatarに表示
作品画像では Image.network を使いましたが、CircleAvatar の背景画像として使う場合は NetworkImage を指定します。
ユーザー名を表示する
プロフィール画像の下には、ユーザー名を表示しています。
const Text(
'Netaflix User',
style: TextStyle(
color: NetflixColors.white,
fontSize: 17,
fontWeight: FontWeight.w800,
),
),
今回は教材用なので、固定で Netaflix User としています。
本格的なアプリでは、ログインしているユーザーの名前を表示します。
教材用
↓
固定のユーザー名
本格的なアプリ
↓
ログイン中のユーザー名
ここまでのまとめ
ここまでで、My Netaflix画面の上部とプロフィール部分を確認しました。
大切なポイントは次の通りです。
- My Netaflix画面は、自分の情報や保存した作品を表示する画面。
MyNetflixPageは、状態を持たないのでStatelessWidgetで作れる。movies.take(4).toList()で、先頭から4件の作品を取り出せる。movies.skip(2).take(4).toList()で、途中から4件の作品を取り出せる。Scaffoldで画面の土台を作る。SafeAreaでノッチやステータスバーを避ける。ListViewを使うと、内容が多い画面でも縦スクロールできる。paddingの下余白を大きくすると、BottomNavigationと重なりにくくなる。Rowでタイトルと編集アイコンを横に並べる。Spacerを使うと、タイトルを左、アイコンを右に分けられる。IconButtonは、アイコンをボタンとして使うWidget。CenterとColumnを使うと、プロフィール画像と名前を中央に並べられる。CircleAvatarは、丸いプロフィール画像を表示するときに便利。NetworkImageを使うと、URL画像をCircleAvatarに表示できる。
MyNetflixCardでメニューカードを作る
ここからは、プロフィール下に表示するメニューカードを見ていきます。
My Netaflix画面では、通知とダウンロードを次のように表示しています。
const MyNetflixCard(
icon: Icons.notifications_none_rounded,
title: 'Notifications',
subtitle: 'Check your latest updates',
),
const SizedBox(height: 12),
const MyNetflixCard(
icon: Icons.file_download_outlined,
title: 'Downloads',
subtitle: 'Watch your saved titles offline',
),
同じようなデザインのカードを2つ作るため、MyNetflixCard という部品にしています。
Notificationsカード
Downloadsカード
↓
同じ形なのでMyNetflixCardとして部品化する
部品化しておくと、あとで「Settings」や「Account」などのカードを増やすときにも使い回せます。
MyNetflixCardのコード
MyNetflixCard は、次のようなWidgetです。
class MyNetflixCard extends StatelessWidget {
const MyNetflixCard({
super.key,
required this.icon,
required this.title,
required this.subtitle,
});
final IconData icon;
final String title;
final String subtitle;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: NetflixColors.darkGray,
borderRadius: BorderRadius.circular(14),
),
padding: const EdgeInsets.all(16),
child: Row(
children: [
Icon(
icon,
color: NetflixColors.white,
size: 28,
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 15.5,
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 3),
Text(
subtitle,
style: TextStyle(
color: NetflixColors.white.withValues(alpha: 0.58),
fontSize: 12.5,
fontWeight: FontWeight.w600,
),
),
],
),
),
const Icon(
Icons.chevron_right_rounded,
color: NetflixColors.white,
),
],
),
);
}
}
このカードは、左にアイコン、中央にタイトルと説明文、右に矢印を置いています。
[アイコン] タイトル
説明文 >
requiredでカードごとの情報を受け取る
MyNetflixCard は、3つの値を受け取ります。
required this.icon,
required this.title,
required this.subtitle,
| 値 | 役割 |
|---|---|
icon | 左側に表示するアイコン |
title | カードの見出し |
subtitle | カードの説明文 |
このようにしておくと、同じカードデザインのまま、中身だけ変えられます。
const MyNetflixCard(
icon: Icons.notifications_none_rounded,
title: 'Notifications',
subtitle: 'Check your latest updates',
),
const MyNetflixCard(
icon: Icons.file_download_outlined,
title: 'Downloads',
subtitle: 'Watch your saved titles offline',
),
同じ部品に違う値を渡すことで、違うカードとして表示できます。
Containerでカードの背景を作る
カード全体は、Container で作っています。
return Container(
decoration: BoxDecoration(
color: NetflixColors.darkGray,
borderRadius: BorderRadius.circular(14),
),
padding: const EdgeInsets.all(16),
child: Row(
...
),
);
背景色は、少し明るい黒系の NetflixColors.darkGray です。
color: NetflixColors.darkGray,
黒背景の画面上に、少し明るいカードを置くことで、メニューとして認識しやすくなります。
borderRadiusで角丸にする
カードの角は、borderRadius で丸めています。
borderRadius: BorderRadius.circular(14),
検索結果カードでは 10 でしたが、My Netaflixのメニューカードでは少し大きめの 14 にしています。
アカウント画面のカードは、少し柔らかく見せると、メニューとして押しやすい印象になります。
角が四角い
↓
硬い印象
少し角丸
↓
ボタン・カードらしい印象
paddingでカード内の余白を作る
カードの中には、余白を入れています。
padding: const EdgeInsets.all(16),
左のアイコン、中央の文字、右の矢印がカードの端にくっつかないようにするためです。
余白があることで、タップできるメニューとして見やすくなります。
余白なし:窮屈
余白あり:押しやすそうに見える
Rowで横並びにする
カードの中身は、Row で横並びにしています。
child: Row(
children: [
Icon(...),
const SizedBox(width: 14),
Expanded(...),
const Icon(Icons.chevron_right_rounded),
],
),
構造は次の通りです。
左:アイコン
中央:タイトル・説明文
右:矢印
メニューカードでは、この並びがよく使われます。
ユーザーは、右側の矢印を見ることで「押すと次の画面に進めそう」と感じます。
Iconで左側のアイコンを表示する
左側のアイコンは、受け取った icon を使って表示しています。
Icon(
icon,
color: NetflixColors.white,
size: 28,
),
icon は、カードごとに違います。
通知カードなら、通知アイコンです。
Icons.notifications_none_rounded
ダウンロードカードなら、ダウンロードアイコンです。
Icons.file_download_outlined
同じ MyNetflixCard でも、アイコンを変えることで意味が変わります。
SizedBoxでアイコンと文字の間に余白を作る
アイコンと文字の間には、横方向の余白があります。
const SizedBox(width: 14),
この余白がないと、アイコンと文字がくっついて読みにくくなります。
アイコンタイトル
余白を入れると、自然なメニューカードになります。
アイコン タイトル
Expandedで文字エリアを広げる
中央のタイトルと説明文は、Expanded で包まれています。
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title),
Text(subtitle),
],
),
),
Expanded を使うことで、左のアイコンと右の矢印以外の残りスペースを、文字エリアとして使えます。
左アイコン 固定
中央テキスト 可変
右矢印 固定
もし説明文が少し長くなっても、中央部分ができるだけ広く使われます。
タイトルと説明文を縦に並べる
中央部分では、Column を使っています。
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title),
const SizedBox(height: 3),
Text(subtitle),
],
)
タイトルを上、説明文を下に置いています。
Notifications
Check your latest updates
タイトルは強く、説明文は控えめに表示します。
タイトルを強く表示する
カードのタイトルは、次のように表示しています。
Text(
title,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 15.5,
fontWeight: FontWeight.w900,
),
),
タイトルはカードの主役なので、白く太く表示します。
Notifications
Downloads
ユーザーがぱっと見たときに、何のカードか分かるようにします。
説明文を控えめに表示する
説明文は、少し薄い白で表示しています。
Text(
subtitle,
style: TextStyle(
color: NetflixColors.white.withValues(alpha: 0.58),
fontSize: 12.5,
fontWeight: FontWeight.w600,
),
),
説明文は補助情報です。
タイトルより目立ちすぎないように、透明度を下げています。
withValues(alpha: 0.58)
情報の重要度に合わせて文字の強さを変えると、画面が読みやすくなります。
chevron_rightで次に進める印象を作る
カードの右端には、矢印アイコンを置いています。
const Icon(
Icons.chevron_right_rounded,
color: NetflixColors.white,
),
chevron_right_rounded は、右向きの矢印のようなアイコンです。
>
これがあると、ユーザーは「このカードを押すと次に進めそう」と感じます。
今回は、まだ遷移先の画面は作っていません。
ただし、UIとしてはアカウント画面らしくなります。
Continue Watchingを表示する
メニューカードの下には、Continue Watching を表示しています。
const SizedBox(height: 28),
RowTitle(title: 'Continue Watching'),
const SizedBox(height: 12),
ContentRow(items: watchingMovies),
RowTitle は、Home画面でも使った見出し用のWidgetです。
Continue Watching
[作品] [作品] [作品]
ここでは、watchingMovies を ContentRow に渡しています。
ContentRow(items: watchingMovies)
ContentRowを再利用する
ContentRow は、横スクロールの作品リストを表示するWidgetです。
Home画面でも使っていました。
My Netaflix画面でも同じWidgetを使っています。
ContentRow(items: watchingMovies)
同じ作品リストUIを何度も作らず、共通Widgetとして再利用しているのがポイントです。
Home画面
↓
ContentRowを使う
My Netaflix画面
↓
ContentRowを使う
これにより、画面ごとのコード量を減らせます。
My Listを表示する
さらに下には、My List を表示しています。
const SizedBox(height: 28),
RowTitle(title: 'My List'),
const SizedBox(height: 12),
ContentRow(items: myListMovies),
こちらは、myListMovies を表示しています。
ContentRow(items: myListMovies)
watchingMovies と myListMovies は、どちらも movies から作った仮のリストです。
final watchingMovies = movies.take(4).toList();
final myListMovies = movies.skip(2).take(4).toList();
本格的なアプリでは、My List はユーザーが追加した作品を表示する場所になります。
画面全体の流れを整理する
My Netaflix画面の流れを整理すると、次のようになります。
MyNetflixPage
↓
Scaffoldで画面の土台を作る
↓
SafeAreaで端末の端を避ける
↓
ListViewで縦スクロール画面にする
↓
上部にタイトルと編集アイコンを表示
↓
中央にプロフィール画像とユーザー名を表示
↓
MyNetflixCardで通知・ダウンロードを表示
↓
Continue Watchingを表示
↓
My Listを表示
Myページは、機能としてはまだシンプルです。
しかし、プロフィール、メニュー、作品リストが入ることで、アプリの完成度が大きく上がります。
まずカスタマイズしてみよう
まずは、ユーザー名を変更してみましょう。
次のコードを探してください。
const Text(
'Netaflix User',
これを好きな名前に変更します。
const Text(
'Guest Profile',
または、日本語にしてもよいです。
const Text(
'ゲストユーザー',
プロフィール画面らしさが変わります。
メニューカードを追加してみよう
Notifications と Downloads の下に、設定カードを追加してみましょう。
const SizedBox(height: 12),
const MyNetflixCard(
icon: Icons.settings_outlined,
title: 'Settings',
subtitle: 'Manage app preferences',
),
これを Downloads の下に追加すると、メニューが3つになります。
Notifications
Downloads
Settings
MyNetflixCard を部品化しているので、カードの追加が簡単です。
Continue Watchingの件数を変えてみよう
現在は、先頭から4件を表示しています。
final watchingMovies = movies.take(4).toList();
これを3件にしたい場合は、次のようにします。
final watchingMovies = movies.take(3).toList();
逆に5件にしたい場合は、次のようにします。
final watchingMovies = movies.take(5).toList();
表示したい件数に合わせて、take の数字を変えます。
My Listの開始位置を変えてみよう
現在の My List は、先頭から2件飛ばして4件表示しています。
final myListMovies = movies.skip(2).take(4).toList();
開始位置を変えたい場合は、skip の数字を変えます。
final myListMovies = movies.skip(1).take(4).toList();
final myListMovies = movies.skip(3).take(4).toList();
skip と take を組み合わせると、同じ movies から違う範囲の作品を取り出せます。
よくあるつまずきポイント
Q. My Netaflix画面がスクロールできません。
画面全体が ListView になっているか確認してください。
ListView(
padding: const EdgeInsets.fromLTRB(18, 18, 18, 110),
children: [
...
],
)
Column だけで作ると、画面の高さに収まらない場合に表示がはみ出すことがあります。
内容が多い画面では、ListView を使うと安心です。
Q. BottomNavigationと内容が重なります。
ListView の下余白を確認してください。
padding: const EdgeInsets.fromLTRB(18, 18, 18, 110),
下の 110 が、BottomNavigationと重ならないための余白です。
重なる場合は、少し大きくしてもよいです。
padding: const EdgeInsets.fromLTRB(18, 18, 18, 130),
Q. プロフィール画像が表示されません。
profileImageUrl が正しいURLか確認してください。
backgroundImage: NetworkImage(profileImageUrl),
ネットワーク画像なので、通信環境によって表示に時間がかかることがあります。
画像URLが無効になっている場合も表示されません。
Q. メニューカードを押しても何も起きません。
今回の MyNetflixCard は、見た目だけのカードです。
まだ onTap は実装していません。
押したときに何かしたい場合は、GestureDetector や InkWell で包んで、onTap を追加します。
GestureDetector(
onTap: () {
// ここに処理を書く
},
child: MyNetflixCard(
icon: Icons.settings_outlined,
title: 'Settings',
subtitle: 'Manage app preferences',
),
)
チャレンジ
チャレンジ1:ユーザー名を日本語にしよう
次のコードを探してください。
const Text(
'Netaflix User',
これを次のように変更します。
const Text(
'ゲストユーザー',
プロフィール名が日本語になるか確認してください。
チャレンジ2:Settingsカードを追加しよう
Downloads カードの下に、次のコードを追加してください。
const SizedBox(height: 12),
const MyNetflixCard(
icon: Icons.settings_outlined,
title: 'Settings',
subtitle: 'Manage app preferences',
),
通知・ダウンロード・設定の3つのカードが並びます。
チャレンジ3:Continue Watchingを3件にしよう
次のコードを探してください。
final watchingMovies = movies.take(4).toList();
これを次のように変更します。
final watchingMovies = movies.take(3).toList();
Continue Watchingに表示される作品数が変わります。
チャレンジ4:My Listの作品範囲を変えよう
次のコードを探してください。
final myListMovies = movies.skip(2).take(4).toList();
これを次のように変更します。
final myListMovies = movies.skip(1).take(4).toList();
My Listに表示される作品が少し変わります。
チャレンジの答え
チャレンジ1の答え
変更前:
const Text(
'Netaflix User',
変更後:
const Text(
'ゲストユーザー',
プロフィール名が日本語になります。
チャレンジ2の答え
追加するコード:
const SizedBox(height: 12),
const MyNetflixCard(
icon: Icons.settings_outlined,
title: 'Settings',
subtitle: 'Manage app preferences',
),
Downloads カードの下に追加します。
チャレンジ3の答え
変更前:
final watchingMovies = movies.take(4).toList();
変更後:
final watchingMovies = movies.take(3).toList();
Continue Watching に表示される作品数が3件になります。
チャレンジ4の答え
変更前:
final myListMovies = movies.skip(2).take(4).toList();
変更後:
final myListMovies = movies.skip(1).take(4).toList();
My List に表示される作品の範囲が変わります。
この節のまとめ
この節では、My Netaflix画面の後半として、通知・ダウンロードカード、視聴中リスト、My Listの表示を学びました。
大切なポイントは次の通りです。
MyNetflixCardを作ると、通知・ダウンロード・設定などのメニューカードを再利用できる。required this.icon、required this.title、required this.subtitleによって、カードごとに中身を変えられる。ContainerとBoxDecorationで、カードの背景色と角丸を作れる。Rowを使うと、アイコン・文字・矢印を横に並べられる。Expandedを使うと、中央の文字エリアを自然に広げられる。chevron_right_roundedを置くと、次の画面に進めるメニューらしく見える。RowTitleとContentRowを再利用すると、Home画面と同じ作品リストUIをMy画面にも表示できる。movies.take(4).toList()で、先頭から4件の作品を取り出せる。movies.skip(2).take(4).toList()で、途中から4件の作品を取り出せる。- Myページは、プロフィール・メニュー・作品リストをまとめることで、アプリ全体の完成度を高める画面になる。
次のステップ
次の節では、iOS用の Info.plist 設定を確認します。アプリ名、画面向き、YouTube表示に関わる設定など、FlutterアプリをiOSで動かすときに大切な項目を見ていきます。画面を作るだけでなく、実機やシミュレーターで正しく動かすための設定も、アプリ開発では重要です。
