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

【まとめ】完成コードをカスタマイズしながらFlutterアプリ開発の流れを身につける

31NETFLIX風動画アプリを作りながらUI・検索・動画再生・共有機能を学ぶFlutter(iOS・Android)アプリ開発
FlutteriOSAndroidMacOSWindows基礎から学ぶ開発アプリ開発

この節で学ぶこと

前の節では、完成したNETAFLIX風アプリをカスタマイズしました。

作品を追加する、色を変える、カテゴリを追加する、共有文を変更することで、完成コードを自分の手で動かす練習をしました。

今回の節では、ここまで作ってきたFlutterアプリ開発の流れをまとめます。

ただコードを写して終わるのではなく、

アプリはどこから始まるのか
画面はどう切り替わるのか
データはどこにあるのか
タップしたら何が起きるのか
どこを変えれば自分のアプリになるのか

を、自分の言葉で説明できるようにしていきます。


まず全体の流れを振り返る

今回作ったNETAFLIX風アプリは、次のような流れで動いていました。

main()
↓
runApp()
↓
NetflixLikeApp
↓
MaterialApp
↓
NetflixShell
↓
BottomNavigationで画面切り替え
↓
Home / Search / Clips / My Netaflix
↓
作品をタップ
↓
MovieDetailPage
↓
Playボタン
↓
MoviePlayerPage

Flutterアプリは、最初に main() から始まります。

そこから runApp() によって、アプリ全体の根っこになるWidgetが画面に表示されます。

今回の場合は、NetflixLikeApp がアプリ全体の入口でした。


ここまで作った主な画面

今回のアプリでは、複数の画面を作りました。

画面役割
HomePage作品を一覧で見せるメイン画面
MovieDetailPage作品の詳細を表示する画面
MoviePlayerPageYouTube動画を再生する画面
ClipsPage縦型ショート動画風に作品を見せる画面
SearchPage作品を検索する画面
MyNetflixPageプロフィール・通知・視聴中リストを表示する画面

最初はバラバラに見えた画面も、完成してみると、それぞれに役割があります。

アプリ開発では、「この画面は何のためにあるのか」を考えることが大切です。


画面切り替えの中心はNetflixShell

今回のアプリでは、BottomNavigationによる画面切り替えを NetflixShell が担当していました。

final pages = const [
  HomePage(),
  SearchPage(),
  ClipsPage(),
  MyNetflixPage(),
];

そして、現在選ばれているタブ番号を currentIndex で管理していました。

int currentIndex = 0;

表示する画面は、次のように決まります。

body: pages[currentIndex],

この仕組みによって、BottomNavigationをタップすると画面が切り替わります。

currentIndex = 0 → HomePage
currentIndex = 1 → SearchPage
currentIndex = 2 → ClipsPage
currentIndex = 3 → MyNetflixPage

状態が変わる画面ではStatefulWidgetを使う

Flutterでは、画面の中で変化する値がある場合、StatefulWidget を使います。

今回のアプリでは、次のような場所で状態が必要でした。

Widget状態
NetflixShell現在選ばれているタブ番号
SearchPage検索欄に入力された文字
MoviePlayerPageYouTubeプレイヤーのController
ClipsPageページ表示や共有処理の管理

たとえば、BottomNavigationでは、タブを押すと currentIndex が変わります。

setState(() {
  currentIndex = index;
});

setState を使うことで、Flutterに「画面を更新してください」と伝えています。


状態が変わらない画面ではStatelessWidgetを使う

一方で、ただ表示するだけの画面や部品は、StatelessWidget で作れます。

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

Widget理由
ContentCard受け取った作品を表示するだけ
RowTitle見出しを表示するだけ
MyNetflixCardメニューカードを表示するだけ
MovieDetailPage受け取った作品情報を表示するだけなら状態を持たない

もちろん、今後Likeボタンや保存状態を追加する場合は、StatefulWidget や状態管理が必要になることもあります。

最初の理解としては、次のように考えると分かりやすいです。

中の値が変わる
↓
StatefulWidget

受け取った情報を表示するだけ
↓
StatelessWidget

MovieItemがアプリの中心データ

今回のアプリで一番重要なデータは、MovieItem でした。

class MovieItem {
  const MovieItem({
    required this.title,
    required this.subtitle,
    required this.description,
    required this.posterUrl,
    required this.backdropUrl,
    required this.youtubeVideoId,
    required this.matchRate,
    required this.year,
    required this.rating,
    required this.seasonLabel,
    required this.category,
  });

  final String title;
  final String subtitle;
  final String description;
  final String posterUrl;
  final String backdropUrl;
  final String youtubeVideoId;
  final int matchRate;
  final int year;
  final String rating;
  final String seasonLabel;
  final String category;
}

MovieItem は、作品1件分の情報をまとめる箱です。

作品タイトル、説明文、画像URL、YouTube動画ID、カテゴリなど、アプリ内で必要な情報が入っています。


moviesを変えるとアプリ全体が変わる

作品一覧は、movies に入っていました。

const movies = [
  MovieItem(...),
  MovieItem(...),
  MovieItem(...),
];

この movies は、いろいろな画面で使われています。

画面movies** の使い方**
Home画面作品一覧として表示
Search画面検索対象として使う
Clips画面縦型動画風に表示
My Netaflix画面視聴中リスト・My Listとして表示
Detail画面選ばれた1作品を表示

つまり、movies に作品を追加すると、アプリ全体に反映されます。

ここが、データを1か所にまとめる大きなメリットです。


画面遷移ではNavigatorを使う

作品カードをタップしたとき、詳細画面へ移動するには Navigator を使いました。

Navigator.of(context).push(
  MaterialPageRoute<void>(
    builder: (context) => MovieDetailPage(movie: movie),
  ),
);

このコードでは、ただ画面を移動しているだけではありません。

MovieDetailPage(movie: movie) のように、選んだ作品データを次の画面に渡しています。

作品カードをタップ
↓
MovieDetailPageへ移動
↓
選んだmovieを渡す
↓
詳細画面にその作品の情報が表示される

Flutterの画面遷移では、「どの画面へ行くか」と「どのデータを渡すか」をセットで考えることが大切です。


YouTube再生では動画IDを使う

詳細画面のPlayボタンを押すと、MoviePlayerPage に移動しました。

MoviePlayerPage(movie: movie)

動画再生では、作品データの中にある youtubeVideoId を使いました。

videoId: widget.movie.youtubeVideoId,

このようにすることで、作品ごとに違うYouTube動画を再生できます。

MovieItem
↓
youtubeVideoIdを持っている
↓
MoviePlayerPageに渡す
↓
YouTubeプレイヤーで再生する

動画アプリでは、作品データと再生機能をつなげることが重要です。


検索機能はqueryとfilteredMoviesで作る

Search画面では、入力された文字を query として管理しました。

String query = '';

文字を入力すると、onChangedquery が更新されます。

onChanged: (value) {
  setState(() {
    query = value;
  });
}

そして、filteredMovies で作品を絞り込みました。

return movies.where((movie) {
  final title = movie.title.toLowerCase();
  final subtitle = movie.subtitle.toLowerCase();
  final description = movie.description.toLowerCase();
  final category = movie.category.toLowerCase();

  return title.contains(keyword) ||
      subtitle.contains(keyword) ||
      description.contains(keyword) ||
      category.contains(keyword);
}).toList();

この流れを理解すると、検索機能の基本が見えてきます。

入力する
↓
queryが変わる
↓
filteredMoviesが変わる
↓
表示される作品が変わる

共通Widgetを使うとコードが整理される

今回のアプリでは、同じようなUIを何度も使いました。

そのため、共通Widgetとして部品化しました。

共通Widget役割
ContentRow横スクロールの作品リスト
ContentCard作品1件分のカード
RowTitleセクション見出し
DetailAction詳細画面のアクションボタン
MyNetflixCardMy画面のメニューカード
SearchResultTile検索結果の1件表示

共通Widgetを使うと、同じUIを何度も書かなくて済みます。

さらに、あとでデザインを変えたいときも、1か所を直せば複数の画面に反映できます。

同じコードを何度も書く
↓
修正が大変

共通Widgetにする
↓
修正しやすい
↓
読みやすい

共有機能は共通関数にまとめる

共有処理は、shareNetaflixMovie にまとめました。

Future<void> shareNetaflixMovie({
  required BuildContext context,
  required MovieItem movie,
}) async {
  await SharePlus.instance.share(
    ShareParams(
      text:
          'NETAFLIXで「${movie.title}」をチェック!\nhttps://www.youtube.com/watch?v=${movie.youtubeVideoId}',
      subject: movie.title,
      sharePositionOrigin: shareOriginFromContext(context),
    ),
  );
}

この関数を作っておくと、詳細画面でもClips画面でも同じ共有処理を使えます。

MovieDetailPage
↓
shareNetaflixMovie

ClipsPage
↓
shareNetaflixMovie

共有文を変更したいときも、この関数を変更すれば複数画面に反映されます。


カスタマイズで理解が深まる

完成コードを読むだけでも勉強になります。

しかし、本当に理解が深まるのは、自分で変更したときです。

今回のカスタマイズでは、次のことに挑戦しました。

カスタマイズ学べること
作品追加データ構造と画面反映の関係
色変更共通色管理とデザイン変更
カテゴリ追加データ分類と検索の関係
共有文変更共通関数と文字列操作
アイコン変更アプリらしさを高める設定
アプリ名変更iOS設定や表示名の考え方

カスタマイズは、ただ見た目を変える作業ではありません。

「このコードは何のためにあるのか」を確認するための練習です。


Flutterアプリ開発の基本サイクル

今回の教材全体を通して、Flutterアプリ開発の基本サイクルを体験しました。

1. 画面を作る
2. データを用意する
3. データを画面に表示する
4. タップで画面遷移する
5. 入力によって表示を変える
6. 外部パッケージを使う
7. iOSやAndroidの設定を整える
8. アイコンやアプリ名を設定する
9. 完成コードを読む
10. 自分でカスタマイズする

この流れは、NETAFLIX風アプリだけでなく、他のアプリにも応用できます。

たとえば、飲食店アプリ、学習アプリ、予約アプリ、商品カタログアプリでも、基本は同じです。


他のアプリに応用するなら

今回のNETAFLIX風アプリは、作品データを表示するアプリでした。

しかし、MovieItem を別のデータに変えれば、いろいろなアプリに応用できます。

応用例MovieItemの代わりになるデータ
飲食店アプリMenuItem
学習アプリLessonItem
ECアプリProductItem
観光アプリSpotItem
予約アプリServiceItem
医療系案内アプリTreatmentItem

たとえば、飲食店アプリなら、作品タイトルの代わりにメニュー名を表示できます。

MovieItem.title
↓
MenuItem.name

動画IDの代わりに、商品詳細ページや予約URLを持たせることもできます。

つまり、今回学んだ構造は、動画アプリだけのものではありません。


どこを変えればオリジナルアプリになるか

NETAFLIX風アプリを別のアプリに変える場合、まずは次の場所を変更します。

変える場所内容
MovieItemデータの形を変える
movies表示するデータを変える
NetflixColors色を変える
HomePage最初に見せたい情報を変える
SearchPage検索対象を変える
MovieDetailPage詳細表示の内容を変える
shareNetaflixMovie共有文を変える
Info.plistアプリ名やiOS設定を変える
icon.pngアプリアイコンを変える

すべてを一気に変える必要はありません。

まずはデータと色を変えるだけでも、かなり違うアプリに見えます。


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

Q. 完成コードを見ても、どこを変えればよいか分かりません。

まずは、次の4か所だけ見れば大丈夫です。

movies
NetflixColors
shareNetaflixMovie
BottomNavigationのpages

作品やデータを変えたいなら movies

色を変えたいなら NetflixColors

共有文を変えたいなら shareNetaflixMovie

画面構成を変えたいなら pages を見ます。


Q. 変更したらエラーが出ました。

エラーが出たときは、まず次の点を確認します。

確認項目よくある原因
カンマMovieItem 同士の区切り忘れ
required必要な項目の書き忘れ
括弧()[]{} の閉じ忘れ
文字列'" の閉じ忘れ
YAMLpubspec.yaml のインデントミス
URL画像URLや動画IDの間違い

エラーは悪いものではありません。

「ここに書き方の問題があります」と教えてくれるメッセージです。


Q. UIを変えたいのに、どのWidgetを触ればよいか分かりません。

画面全体を変えたいなら、各Pageを見ます。

HomePage
SearchPage
ClipsPage
MyNetflixPage
MovieDetailPage

作品カードの見た目を変えたいなら、ContentCard を見ます。

検索結果の見た目を変えたいなら、SearchResultTile を見ます。

My画面のメニューカードを変えたいなら、MyNetflixCard を見ます。

まずは、「どの見た目を変えたいのか」を決めてから、該当するWidgetを探しましょう。


チャレンジ

チャレンジ1:自分の言葉でアプリの流れを説明しよう

次の流れを、声に出して説明してみましょう。

main()
↓
NetflixLikeApp
↓
NetflixShell
↓
HomePage
↓
MovieDetailPage
↓
MoviePlayerPage

ポイントは、コードを暗記することではありません。

「アプリがどこから始まり、どう画面がつながるのか」を説明できることです。


チャレンジ2:MovieItemを別のデータに置き換えて考えよう

動画アプリではなく、飲食店メニューアプリにするとしたら、MovieItem はどのような名前にできますか。

例です。

MovieItem
↓
MenuItem

そして、次の項目を考えてみましょう。

MovieItemMenuItemなら
titlename
descriptiondescription
posterUrlimageUrl
categorycategory
ratingprice

データの形を変えると、アプリのテーマも変えられます。


チャレンジ3:自分だけのカスタマイズ案を3つ書こう

次のように、自分のカスタマイズ案を書いてみましょう。

1. アプリ名を変える
2. 作品データを自分の好きなジャンルにする
3. 共有文を日本語で自然な文章にする

できれば、「どのファイル・どのコードを変えるか」まで書いてみましょう。


チャレンジ4:エラーが出たときの確認順を作ろう

自分用のエラーチェックリストを作ってみましょう。

例です。

1. 保存したか確認する
2. 赤線の場所を見る
3. カンマ忘れを確認する
4. 括弧の閉じ忘れを確認する
5. required項目を書いたか確認する
6. ターミナルのエラー文を読む

エラー対応の型を持っておくと、次の開発がかなり楽になります。


チャレンジの答え

チャレンジ1の答え

アプリは main() から始まります。

main() の中で runApp(const NetflixLikeApp()) が実行され、NetflixLikeApp がアプリ全体の入口になります。

NetflixLikeApp の中では MaterialApp を使い、最初の画面として NetflixShell を表示します。

NetflixShell はBottomNavigationで画面を切り替えます。

Home画面で作品をタップすると、MovieDetailPage に移動し、Playボタンを押すと MoviePlayerPage に移動してYouTube動画を再生します。


チャレンジ2の答え

飲食店メニューアプリにする場合、MovieItemMenuItem のように変更できます。

例です。

class MenuItem {
  const MenuItem({
    required this.name,
    required this.description,
    required this.imageUrl,
    required this.price,
    required this.category,
  });

  final String name;
  final String description;
  final String imageUrl;
  final int price;
  final String category;
}

このように、データの形を変えることで、動画アプリの構造を別ジャンルのアプリに応用できます。


チャレンジ3の答え

カスタマイズ案の例です。

カスタマイズ案変更する場所
アプリ名を MY MOVIE にするInfo.plistMaterialApp.title
アクセントカラーを青にするNetflixColors.red
作品ジャンルをアニメ中心にするmoviescategory
共有文を日本語にするshareNetaflixMovie
アイコンを変更するassets/icon/icon.png

どこを変えればよいかが分かると、自分のアイデアをコードに反映しやすくなります。


チャレンジ4の答え

エラーが出たときの確認順の例です。

1. ファイルを保存したか確認する
2. エラーが出ている行を見る
3. 直前に変更した場所を見る
4. カンマ忘れを確認する
5. 括弧の閉じ忘れを確認する
6. 文字列の閉じ忘れを確認する
7. required項目を書いたか確認する
8. pubspec.yamlならインデントを確認する
9. flutter pub getを実行したか確認する
10. エラー文をそのまま検索・質問する

エラーが出たときは、慌てずに「最後に変えた場所」から確認するのが基本です。


このページのまとめ

このページでは、完成したNETAFLIX風アプリを振り返りながら、Flutterアプリ開発の流れを整理しました。

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

  • Flutterアプリは main() から始まる。
  • runApp() に渡したWidgetが、アプリ全体の根っこになる。
  • MaterialApp でアプリ全体の設定を行う。
  • NetflixShell がBottomNavigationによる画面切り替えを担当する。
  • StatefulWidget は、変化する状態を持つ画面で使う。
  • StatelessWidget は、受け取った情報を表示するだけの部品で使う。
  • MovieItem は、作品1件分のデータ構造。
  • movies は、アプリ全体で使う作品一覧。
  • Navigator を使うと、画面遷移ができる。
  • 画面遷移では、次の画面にデータを渡すことが重要。
  • youtubeVideoId によって、作品ごとのYouTube動画を再生できる。
  • queryfilteredMovies によって、検索機能を作れる。
  • 共通Widgetを使うと、コードが整理され、修正もしやすくなる。
  • 共有処理は共通関数にまとめると便利。
  • 完成コードをカスタマイズすると、コードの役割が理解しやすくなる。
  • データ、色、共有文、アイコン、アプリ名を変えるだけでも、オリジナルアプリに近づけられる。
  • エラーが出たら、最後に変更した場所から落ち着いて確認する。

次のステップ

ここまでで、NETAFLIX風アプリ制作教材の大きな流れは完了です。

次に進むなら、次の発展課題がおすすめです。

発展課題学べること
お気に入り保存機能状態管理・ローカル保存
ログイン機能FirebaseやSupabase連携
作品データの外部化JSON・API・データベース
予約・購入機能決済やフォーム設計
管理画面データ追加・編集・削除
デプロイ・配布アプリ公開の流れ

今回作ったアプリは、完成形でありながら、発展の土台でもあります。

まずは完成コードを何度も触り、「変えたらどうなるか」を試してみることが、次の成長につながります。

教材トップへ戻る