Flutterアプリケーション開発概論

【LikeとMy List】setStateでハートや保存ボタンのON/OFFを切り替える

この節で学ぶこと

前の節では、作品詳細画面にタイトル、説明文、メタ情報、Playボタン、Downloadボタン、アクションボタンを表示する方法を学びました。

今回の節では、その中でも特に LikeボタンMy Listボタン に注目します。

動画アプリでは、作品詳細画面に次のようなボタンがよくあります。

+ My List
♡ Like
↗ Share

このうち、My ListLike は、押すたびに見た目が変わります。

My Listを押す
↓
+ が ✓ に変わる

Likeを押す
↓
♡ が ♥ に変わる

このように、ユーザーの操作によって画面の見た目を変えるには、Flutterでは setState を使います。

この節では、setState を使って、保存ボタンやハートボタンのON/OFFを切り替える仕組みを学びます。


今回見るコード

詳細画面では、次の2つの状態を持っています。

class _MovieDetailPageState extends State<MovieDetailPage> {
  bool isInMyList = false;
  bool isLiked = false;

isInMyList は、作品がMy Listに追加されているかどうかを表します。

isLiked は、作品にLikeしているかどうかを表します。

それぞれ、最初は false です。

isInMyList = false
↓
まだMy Listに入っていない

isLiked = false
↓
まだLikeしていない

そして、画面の中では次のように使っています。

DetailActions(
  isInMyList: isInMyList,
  isLiked: isLiked,
  onToggleMyList: () {
    setState(() {
      isInMyList = !isInMyList;
    });
  },
  onToggleLike: () {
    setState(() {
      isLiked = !isLiked;
    });
  },
  onShare: () => shareNetaflixMovie(
    context: context,
    movie: movie,
  ),
),

このコードが、My ListとLikeのON/OFF切り替えの中心です。


状態とは何か

まず、「状態」という言葉を整理しましょう。

アプリの画面には、変わらないものと変わるものがあります。

たとえば、作品タイトルは基本的に変わりません。

Squid Game
Wednesday
Stranger Things

一方で、LikeボタンやMy Listボタンは、ユーザーが押すことで変わります。

Likeしていない
↓
Likeしている

保存していない
↓
保存している

このように、画面の中で変わる情報のことを「状態」と考えると分かりやすいです。

Flutterでは、この状態を変数で持ちます。

今回の場合は、次の2つです。

bool isInMyList = false;
bool isLiked = false;

boolとは?

bool は、truefalse のどちらかを入れる型です。

bool isLiked = false;

これは、isLiked という変数に false を入れているという意味です。

bool は、ON/OFFを表すときによく使います。

状態boolで表すと
Likeしているtrue
Likeしていないfalse
My Listに入っているtrue
My Listに入っていないfalse
表示するtrue
表示しないfalse

今回のように、ボタンのON/OFFを切り替えるときには、bool がとても便利です。


最初はfalseにしておく

詳細画面を開いた直後は、次のようになっています。

bool isInMyList = false;
bool isLiked = false;

これは、初期状態ではMy Listにも入っておらず、Likeもされていないという意味です。

初期状態
↓
My List:OFF
Like:OFF

もちろん、実際のアプリでは、ユーザーが過去に保存した作品やLikeした作品をデータベースから読み込むことがあります。

ただし、この教材ではまず画面の中だけでON/OFFを切り替える基本を学びます。

そのため、最初は false にしています。


StatefulWidgetが必要な理由

isInMyListisLiked のように、画面の中で変わる値を持つ場合は、StatefulWidget を使います。

class MovieDetailPage extends StatefulWidget {

もし StatelessWidget だと、基本的には画面の中で状態を持って更新することができません。

今回の詳細画面では、ユーザーがボタンを押すたびに見た目が変わります。

Likeボタンを押す
↓
ハートが変わる

My Listボタンを押す
↓
アイコンが変わる

このような「画面が変化するUI」には、StatefulWidget が向いています。


Stateクラスで状態を管理する

StatefulWidget では、実際の状態は State クラスの中に書きます。

class _MovieDetailPageState extends State<MovieDetailPage> {
  bool isInMyList = false;
  bool isLiked = false;

この _MovieDetailPageState が、詳細画面の状態を持っています。

isInMyListisLiked は、この画面の中で使われる変数です。

_MovieDetailPageState
├── isInMyList
└── isLiked

この2つの値を変えることで、My ListボタンとLikeボタンの見た目を切り替えます。


setStateとは?

setState は、状態を変えて、画面を更新するための関数です。

今回のコードでは、次のように使っています。

setState(() {
  isLiked = !isLiked;
});

このコードは、次の2つのことをしています。

1. isLikedの値を反対にする
2. 画面をもう一度描き直す

ここがとても大切です。

ただ変数の値を変えるだけでは、画面が変わらないことがあります。

Flutterに「状態が変わったので、画面を更新してください」と伝えるために setState を使います。


setStateを使わないとどうなる?

たとえば、次のように書いたとします。

isLiked = !isLiked;

この場合、変数の値は変わります。

しかし、Flutterが画面を更新してくれない場合があります。

つまり、内部では isLiked が変わっているのに、画面上のハートアイコンは変わらないかもしれません。

そこで、次のように setState の中で変更します。

setState(() {
  isLiked = !isLiked;
});

こうすると、Flutterは「状態が変わった」と分かり、画面を再描画してくれます。


! は反対にする記号

Likeの切り替えでは、次のようなコードがあります。

isLiked = !isLiked;

この ! は、真偽値を反対にする記号です。

元の値!** をつけた値**
truefalse
falsetrue

つまり、isLiked = !isLiked; は、次のような意味です。

isLikedがfalseならtrueにする
isLikedがtrueならfalseにする

ボタンを押すたびにON/OFFを切り替えたい場合、とてもよく使う書き方です。


Likeボタンの切り替え

Likeボタンでは、次のコードを使っています。

onToggleLike: () {
  setState(() {
    isLiked = !isLiked;
  });
},

これを日本語で読むと、次のようになります。

Likeボタンが押されたら
↓
setStateを実行する
↓
isLikedを反対にする
↓
画面を更新する

最初は isLiked = false です。

isLiked = false
↓
空のハートを表示

ボタンを押すと、true になります。

isLiked = true
↓
塗りつぶしのハートを表示

もう一度押すと、また false に戻ります。

isLiked = false
↓
空のハートに戻る

My Listボタンの切り替え

My Listボタンも、考え方は同じです。

onToggleMyList: () {
  setState(() {
    isInMyList = !isInMyList;
  });
},

これは、次の意味です。

My Listボタンが押されたら
↓
setStateを実行する
↓
isInMyListを反対にする
↓
画面を更新する

最初は isInMyList = false です。

isInMyList = false
↓
+アイコンを表示

ボタンを押すと、true になります。

isInMyList = true
↓
チェックアイコンを表示

もう一度押すと、また false に戻ります。

isInMyList = false
↓
+アイコンに戻る

DetailActionsに状態を渡す

詳細画面では、DetailActions に状態を渡しています。

DetailActions(
  isInMyList: isInMyList,
  isLiked: isLiked,
  onToggleMyList: () {
    setState(() {
      isInMyList = !isInMyList;
    });
  },
  onToggleLike: () {
    setState(() {
      isLiked = !isLiked;
    });
  },
  onShare: () => shareNetaflixMovie(
    context: context,
    movie: movie,
  ),
),

ここで大切なのは、DetailActions 自体が状態を持っているのではなく、親である _MovieDetailPageState が状態を持っているということです。

_MovieDetailPageState
├── isInMyList
├── isLiked
└── DetailActionsに渡す

DetailActions は、渡された値をもとに表示を変えています。


なぜ親で状態を持つのか

今回、isInMyListisLiked は、MovieDetailPage の中で管理しています。

理由は、詳細画面全体に関係する状態だからです。

DetailActions の中だけで状態を持つこともできますが、親で管理しておくと、他の場所でも同じ状態を使いやすくなります。

たとえば、今後次のような表示を追加したいとします。

この作品はMy Listに追加済みです

この表示を詳細画面の別の場所に出したい場合、親が状態を持っていた方が扱いやすいです。

親が状態を持つ
↓
必要な子Widgetに状態を渡す
↓
画面全体で状態を使いやすい

Flutterでは、この考え方をよく使います。


DetailActionsの役割

DetailActions は、My List、Like、Shareの3つのボタンを横に並べるためのWidgetです。

class DetailActions extends StatelessWidget {
  const DetailActions({
    super.key,
    required this.isInMyList,
    required this.isLiked,
    required this.onToggleMyList,
    required this.onToggleLike,
    required this.onShare,
  });

  final bool isInMyList;
  final bool isLiked;
  final VoidCallback onToggleMyList;
  final VoidCallback onToggleLike;
  final VoidCallback onShare;

受け取っている値は、次の5つです。

役割
isInMyListboolMy Listに入っているか
isLikedboolLikeされているか
onToggleMyListVoidCallbackMy Listボタンを押したときの処理
onToggleLikeVoidCallbackLikeボタンを押したときの処理
onShareVoidCallbackShareボタンを押したときの処理

DetailActions は状態を受け取り、それに合わせてアイコンや色を変えます。


VoidCallbackとは?

VoidCallback は、「引数を受け取らず、戻り値も返さない関数」の型です。

少し難しく聞こえますが、ボタンを押したときの処理によく使います。

たとえば、次のような処理です。

onToggleLike: () {
  setState(() {
    isLiked = !isLiked;
  });
},

この関数は、何か値を受け取っているわけではありません。

そして、何か値を返しているわけでもありません。

ただ、押されたときに処理を実行しています。

このような関数を受け取るときに、VoidCallback を使います。


DetailActionsの中でボタンを並べる

DetailActions の中では、Row を使ってボタンを横に並べます。

@override
Widget build(BuildContext context) {
  return Row(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
      DetailAction(
        icon: isInMyList
            ? Icons.check_rounded
            : Icons.add_rounded,
        label: 'My List',
        active: isInMyList,
        onTap: onToggleMyList,
      ),
      DetailAction(
        icon: isLiked
            ? Icons.favorite_rounded
            : Icons.favorite_border_rounded,
        label: 'Like',
        active: isLiked,
        onTap: onToggleLike,
      ),
      DetailAction(
        icon: Icons.share_outlined,
        label: 'Share',
        active: false,
        onTap: onShare,
      ),
    ],
  );
}

画面上では、次のように並びます。

My List   Like   Share

同じ形のボタンを3つ並べるために、DetailAction という部品を使っています。


mainAxisAlignment: spaceAroundとは?

Row には、次の指定があります。

mainAxisAlignment: MainAxisAlignment.spaceAround,

これは、横方向に並ぶ要素の間隔を自動で調整する指定です。

spaceAround を使うと、各ボタンの周りに均等な余白ができます。

  My List    Like    Share

スマホ画面では、ボタン同士が近すぎると押しにくくなります。

そのため、適度に間隔を空けて並べています。


My Listのアイコンを切り替える

My Listボタンでは、isInMyList の値によってアイコンを変えています。

icon: isInMyList
    ? Icons.check_rounded
    : Icons.add_rounded,

これは、三項演算子です。

意味は次の通りです。

isInMyListがtrueなら、チェックアイコン
isInMyListがfalseなら、追加アイコン

表にすると、こうなります。

isInMyList表示するアイコン
falseIcons.add_rounded
trueIcons.check_rounded

これによって、ボタンを押すたびに「追加前」と「追加後」の見た目が切り替わります。


Likeのアイコンを切り替える

Likeボタンも同じです。

icon: isLiked
    ? Icons.favorite_rounded
    : Icons.favorite_border_rounded,

意味は次の通りです。

isLikedがtrueなら、塗りつぶしハート
isLikedがfalseなら、空のハート

表にすると、こうなります。

isLiked表示するアイコン
falseIcons.favorite_border_rounded
trueIcons.favorite_rounded

bool と三項演算子を組み合わせることで、状態に応じてUIを変えられます。


activeで色も切り替える

DetailAction には、active という値も渡しています。

DetailAction(
  icon: isLiked
      ? Icons.favorite_rounded
      : Icons.favorite_border_rounded,
  label: 'Like',
  active: isLiked,
  onTap: onToggleLike,
),

ここでは、active: isLiked としています。

つまり、Likeされているときは activetrue になります。

My Listも同じです。

active: isInMyList,

この active を使って、DetailAction の中で文字色やアイコン色を変えます。


ここまでのまとめ

ここまでで、LikeとMy ListのON/OFF切り替えの基本を確認しました。

大切なポイントは次の通りです。

  • ON/OFFの状態は bool で管理できる。
  • isInMyList はMy Listに入っているかを表す。
  • isLiked はLikeされているかを表す。
  • 状態が変わる画面には StatefulWidget を使う。
  • setState の中で状態を変えると、画面が更新される。
  • ! を使うと、truefalse を反転できる。
  • DetailActions に状態と処理を渡して、子Widget側で表示を変える。
  • 三項演算子を使うと、状態に応じてアイコンを切り替えられる。
  • active を渡すことで、選択中かどうかを見た目に反映できる。

DetailActionの中でactiveを使う

前半では、DetailActions から DetailActionactive を渡すところまで見ました。

ここからは、DetailAction の中で active を使って、アイコンや文字の色を切り替える仕組みを見ていきます。

DetailAction は、My List、Like、Shareの1つ1つのボタンを作る部品です。

class DetailAction extends StatelessWidget {
  const DetailAction({
    super.key,
    required this.icon,
    required this.label,
    required this.active,
    required this.onTap,
  });

  final IconData icon;
  final String label;
  final bool active;
  final VoidCallback onTap;

この中で、activetruefalse かによって、ボタンの見た目を変えます。


activeで色を切り替える

DetailActionbuild の中では、次のように色を決めています。

@override
Widget build(BuildContext context) {
  final color = active ? NetflixColors.white : NetflixColors.muted;

  return GestureDetector(
    behavior: HitTestBehavior.opaque,
    onTap: onTap,
    child: SizedBox(
      width: 88,
      child: Column(
        children: [
          Icon(icon, color: color, size: 28),
          const SizedBox(height: 6),
          Text(
            label,
            style: TextStyle(
              color: color,
              fontSize: 11.5,
              fontWeight: FontWeight.w700,
            ),
          ),
        ],
      ),
    ),
  );
}

特に大事なのは、この部分です。

final color = active ? NetflixColors.white : NetflixColors.muted;

これは、次の意味です。

activeがtrueなら白
activeがfalseなら薄いグレー

表にすると、こうです。

active
trueNetflixColors.white
falseNetflixColors.muted

つまり、ONになっているボタンは白く表示され、OFFのボタンは少し薄い色で表示されます。


アイコンと文字に同じ色を使う

決めた color は、アイコンと文字の両方に使っています。

Icon(icon, color: color, size: 28),
Text(
  label,
  style: TextStyle(
    color: color,
    fontSize: 11.5,
    fontWeight: FontWeight.w700,
  ),
),

これにより、ボタン全体の状態が分かりやすくなります。

OFF:薄いグレーのアイコンと文字
ON:白いアイコンと文字

アイコンだけ変えるよりも、文字色も一緒に変えた方が、ユーザーに状態が伝わりやすくなります。


GestureDetectorでタップを受け取る

DetailAction も、GestureDetector で包まれています。

return GestureDetector(
  behavior: HitTestBehavior.opaque,
  onTap: onTap,
  child: SizedBox(
    width: 88,
    child: Column(
      children: [
        ...
      ],
    ),
  ),
);

GestureDetector は、タップなどの操作を受け取るためのWidgetです。

ここでは、ボタンを押したときに onTap を実行します。

onTap: onTap,

この onTap には、親から渡された処理が入っています。

My Listの場合は、onToggleMyList が渡されています。

Likeの場合は、onToggleLike が渡されています。

Shareの場合は、onShare が渡されています。


behavior: HitTestBehavior.opaqueとは?

GestureDetector には、次の指定があります。

behavior: HitTestBehavior.opaque,

これは、タップ判定の範囲を分かりやすくするための指定です。

DetailAction は、アイコンと文字だけでできています。

もしタップ判定がアイコンや文字の部分だけだと、少し押しにくくなることがあります。

そこで、SizedBox(width: 88) 全体をタップしやすくするために、HitTestBehavior.opaque を指定しています。

アイコンだけでなく
ボタンの幅全体をタップしやすくする

スマホアプリでは、見た目以上に「押しやすい範囲」を作ることが大切です。


SizedBoxでボタンの幅をそろえる

DetailAction の中では、SizedBox で幅を決めています。

SizedBox(
  width: 88,
  child: Column(
    children: [
      ...
    ],
  ),
),

My List、Like、Shareの3つのボタンの幅を同じにするためです。

[ My List ] [  Like  ] [ Share  ]

幅がバラバラだと、横並びにしたときに少し乱れて見えます。

同じ幅にしておくと、整ったUIになります。


Columnでアイコンと文字を縦に並べる

DetailAction の中では、Column を使っています。

Column(
  children: [
    Icon(icon, color: color, size: 28),
    const SizedBox(height: 6),
    Text(
      label,
      style: TextStyle(
        color: color,
        fontSize: 11.5,
        fontWeight: FontWeight.w700,
      ),
    ),
  ],
)

並びはこうです。

アイコン
↓
文字

動画アプリの詳細画面では、このようにアイコンを上、ラベルを下に置く操作ボタンがよく使われます。


Shareだけactiveがfalseの理由

DetailActions のShareボタンでは、次のように書いています。

DetailAction(
  icon: Icons.share_outlined,
  label: 'Share',
  active: false,
  onTap: onShare,
),

Shareは、My ListやLikeと違って、ON/OFFを持つボタンではありません。

押したら共有画面を開くだけです。

Shareを押す
↓
共有画面を開く
↓
状態は変わらない

そのため、active: false にしています。

一方で、My ListとLikeはON/OFFがあります。

active: isInMyList
active: isLiked

この違いを理解しておくと、ボタンごとの役割が分かりやすくなります。


状態が変わる流れをもう一度整理しよう

Likeボタンを押したときの流れを、もう一度整理します。

1. Likeボタンを押す
2. DetailActionのonTapが実行される
3. 親から渡されたonToggleLikeが呼ばれる
4. setStateが動く
5. isLiked = !isLiked で値が反転する
6. 画面が再描画される
7. isLikedに応じてアイコンと色が変わる

My Listも同じです。

1. My Listボタンを押す
2. DetailActionのonTapが実行される
3. 親から渡されたonToggleMyListが呼ばれる
4. setStateが動く
5. isInMyList = !isInMyList で値が反転する
6. 画面が再描画される
7. isInMyListに応じてアイコンと色が変わる

このように、setState は「値を変える」だけでなく、「画面を更新する合図」でもあります。


setStateの中で複数の状態を変えることもできる

今回のコードでは、LikeとMy Listを別々に切り替えています。

setState(() {
  isLiked = !isLiked;
});
setState(() {
  isInMyList = !isInMyList;
});

ただし、必要であれば、setState の中で複数の状態をまとめて変えることもできます。

たとえば、Likeしたら自動でMy Listにも追加したい場合は、次のようにできます。

setState(() {
  isLiked = true;
  isInMyList = true;
});

ただし、これはアプリの仕様によります。

教材の今の段階では、LikeとMy Listは別々に切り替える方が分かりやすいです。


状態は今だけ保存される

ここで大切な注意点があります。

今回の isLikedisInMyList は、画面の中だけで管理されています。

bool isInMyList = false;
bool isLiked = false;

そのため、アプリを閉じたり、画面を作り直したりすると、状態は元に戻ります。

Likeする
↓
ハートがONになる
↓
アプリを閉じる
↓
もう一度開く
↓
またOFFに戻る

これは、データベースや端末内保存に記録していないからです。

実際のアプリで保存状態を残したい場合は、次のような仕組みが必要になります。

保存方法
端末内に保存SharedPreferencesなど
サーバーに保存Supabase、Firebaseなど
ログインユーザーごとに保存Auth + Database

この教材では、まず setState で画面の中の状態を変える基本を学んでいます。


UIだけでなくデータ保存へ発展できる

今のコードは、見た目のON/OFFだけです。

しかし、この考え方は、あとからデータ保存にも発展できます。

たとえば、Likeボタンを押したときに、次のような処理を追加できます。

setStateで画面を変える
↓
データベースに保存する
↓
次回開いたときに保存状態を読み込む

今後、本格的なアプリにする場合は、次のような流れになります。

// イメージ
onToggleLike: () async {
  setState(() {
    isLiked = !isLiked;
  });

  // このあと、データベースに保存する処理を追加する
}

まずは画面上でON/OFFが切り替わることを理解し、そのあと保存機能へ進むと分かりやすいです。


よくあるつまずきポイント

Q. ボタンを押してもアイコンが変わりません。

setState の中で状態を変えているか確認してください。

setState(() {
  isLiked = !isLiked;
});

次のように setState なしで書くと、画面が更新されないことがあります。

isLiked = !isLiked;

状態を変えて画面に反映したいときは、setState を使いましょう。


Q. setState が使えません。

setState は、StatefulWidgetState クラスの中で使います。

次のような StatelessWidget の中では使えません。

class DetailActions extends StatelessWidget {

今回の場合、setState_MovieDetailPageState の中で使っています。

class _MovieDetailPageState extends State<MovieDetailPage> {

子Widgetである DetailActions には、親から処理を渡しています。


Q. LikeとMy Listが同時に変わってしまいます。

isLikedisInMyList を別々の変数にしているか確認してください。

bool isInMyList = false;
bool isLiked = false;

Likeボタンでは isLiked だけを変えます。

setState(() {
  isLiked = !isLiked;
});

My Listボタンでは isInMyList だけを変えます。

setState(() {
  isInMyList = !isInMyList;
});

同じ変数を使ってしまうと、2つのボタンが同時に変わる原因になります。


Q. ShareボタンもON/OFFしてしまいます。

Shareは状態を持たないボタンです。

そのため、active は固定で false にしています。

DetailAction(
  icon: Icons.share_outlined,
  label: 'Share',
  active: false,
  onTap: onShare,
),

Shareは押したら共有画面を開くボタンなので、LikeやMy Listとは役割が違います。


チャレンジ

チャレンジ1:Likeの初期状態をONにしてみよう

次のコードを探してください。

bool isLiked = false;

これを次のように変更します。

bool isLiked = true;

詳細画面を開いた直後から、LikeボタンがONになっているか確認してください。


チャレンジ2:My Listの初期状態をONにしてみよう

次のコードを探してください。

bool isInMyList = false;

これを次のように変更します。

bool isInMyList = true;

詳細画面を開いた直後から、My Listボタンがチェック表示になるか確認してください。


チャレンジ3:LikeボタンのラベルをFavoriteに変えよう

次のコードを探してください。

label: 'Like',

これを次のように変更します。

label: 'Favorite',

ボタンの文字が変わるか確認してください。


チャレンジ4:My ListがONのときのアイコンを変更しよう

次のコードを探してください。

icon: isInMyList
    ? Icons.check_rounded
    : Icons.add_rounded,

これを次のように変更します。

icon: isInMyList
    ? Icons.bookmark_rounded
    : Icons.add_rounded,

My Listを押したとき、チェックではなくブックマークのアイコンに変わるか確認してください。


チャレンジの答え

チャレンジ1の答え

変更前:

bool isLiked = false;

変更後:

bool isLiked = true;

詳細画面を開いた直後から、LikeボタンがONになります。


チャレンジ2の答え

変更前:

bool isInMyList = false;

変更後:

bool isInMyList = true;

詳細画面を開いた直後から、My ListボタンがONになります。


チャレンジ3の答え

変更前:

label: 'Like',

変更後:

label: 'Favorite',

Likeボタンの表示文字が Favorite に変わります。


チャレンジ4の答え

変更前:

icon: isInMyList
    ? Icons.check_rounded
    : Icons.add_rounded,

変更後:

icon: isInMyList
    ? Icons.bookmark_rounded
    : Icons.add_rounded,

My ListがONのとき、チェックアイコンではなくブックマークアイコンになります。


この節のまとめ

この節では、setState を使って、LikeボタンとMy ListボタンのON/OFFを切り替える方法を学びました。

大切なポイントは次の通りです。

  • bool は、ON/OFFの状態を管理するときに便利。
  • isLiked はLikeされているかどうかを表す。
  • isInMyList はMy Listに追加されているかどうかを表す。
  • setState の中で状態を変えると、画面が再描画される。
  • ! を使うと、truefalse を反転できる。
  • 親Widgetで状態を持ち、子Widgetに状態と処理を渡すと管理しやすい。
  • 三項演算子を使うと、状態に応じてアイコンを切り替えられる。
  • active を使うと、選択中かどうかで色を変えられる。
  • HitTestBehavior.opaque を使うと、ボタンのタップ範囲を広げやすい。
  • 今回の状態は画面内だけで保存されるため、アプリを閉じると元に戻る。
  • 本格的に保存したい場合は、端末内保存やデータベース保存へ発展させる。

次のステップ

次の節では、YouTube再生画面を作ります。

youtube_player_iframe を使って、作品データに登録した youtubeVideoId をもとに、アプリ内で予告編を再生する方法を学びます。

詳細画面の Play Trailer ボタンから再生画面へ移動する流れも、あわせて確認していきましょう。

教材トップへ戻る