
【YouTube再生】youtube_player_iframeで作品トレーラーを再生する
この節で学ぶこと
前の節では、setState を使って、LikeボタンやMy ListボタンのON/OFFを切り替える方法を学びました。
今回の節では、作品詳細画面にある Play Trailerボタン を押したときに、YouTubeの予告編をアプリ内で再生する仕組みを学びます。
このアプリでは、YouTube再生に youtube_player_iframe というパッケージを使っています。
作品詳細画面
↓
Play Trailerボタンを押す
↓
YouTubePlayerPageへ移動する
↓
movie.youtubeVideoIdを使って動画を再生する
つまり、詳細画面で選ばれた作品の youtubeVideoId を使って、その作品のトレーラーを再生します。
今回見るコード
YouTube再生画面は、YouTubePlayerPage というクラスで作っています。
class YouTubePlayerPage extends StatefulWidget {
const YouTubePlayerPage({
super.key,
required this.movie,
});
final MovieItem movie;
@override
State<YouTubePlayerPage> createState() => _YouTubePlayerPageState();
}
この画面も、詳細画面と同じように MovieItem を受け取っています。
final MovieItem movie;
なぜなら、作品ごとに再生するYouTube動画が違うからです。
たとえば、Squid Game なら Squid Game の動画ID、Wednesday なら Wednesday の動画IDを使います。
YouTube動画IDとは?
YouTubeの動画には、それぞれ固有のIDがあります。
たとえば、YouTubeのURLが次のような形だったとします。
https://www.youtube.com/watch?v=oqxAJKy0ii4
この場合、動画IDはこの部分です。
oqxAJKy0ii4
今回のアプリでは、作品データの中に、この動画IDを保存しています。
youtubeVideoId: 'oqxAJKy0ii4',
YouTube再生画面では、この youtubeVideoId を使って動画を読み込みます。
MovieItemの中に動画IDを持たせる
作品データには、youtubeVideoId という項目があります。
class MovieItem {
const MovieItem({
required this.title,
required this.subtitle,
required this.description,
required this.posterUrl,
required this.backdropUrl,
required this.youtubeVideoId,
required this.year,
required this.rating,
required this.seasonLabel,
required this.category,
required this.matchRate,
required this.homeCategory,
});
final String title;
final String subtitle;
final String description;
final String posterUrl;
final String backdropUrl;
final String youtubeVideoId;
final String year;
final String rating;
final String seasonLabel;
final String category;
final int matchRate;
final HomeCategory homeCategory;
}
この中で、今回使うのは次の部分です。
final String youtubeVideoId;
String なので、文字列として動画IDを持っています。
作品データの例
たとえば、作品データは次のように登録されています。
MovieItem(
title: 'Squid Game',
subtitle: 'A survival game with deadly stakes',
description:
'Hundreds of cash-strapped players accept a strange invitation to compete in children’s games for a tempting prize.',
posterUrl:
'https://image.tmdb.org/t/p/w500/dDlEmu3EZ0Pgg93K2SVNLCjCSvE.jpg',
backdropUrl:
'https://image.tmdb.org/t/p/w1280/oaGvjB0DvdhXhOAuADfHb261ZHa.jpg',
youtubeVideoId: 'oqxAJKy0ii4',
year: '2021',
rating: '18+',
seasonLabel: 'Season 1',
category: 'TV Drama',
matchRate: 98,
homeCategory: HomeCategory.shows,
),
この中の youtubeVideoId を使って、YouTube動画を再生します。
youtubeVideoId: 'oqxAJKy0ii4',
このように、作品情報の中に動画IDを持たせておくことで、作品ごとに違うトレーラーを再生できます。
詳細画面からYouTube再生画面へ移動する
詳細画面には、Play Trailerボタンがあります。
PlayButton(
label: 'Play Trailer',
onTap: () {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => YouTubePlayerPage(movie: movie),
),
);
},
),
このボタンを押すと、YouTubePlayerPage へ移動します。
YouTubePlayerPage(movie: movie)
ここでも、movie を渡しています。
つまり、詳細画面で表示していた作品データを、そのままYouTube再生画面へ渡しています。
データの流れを整理しよう
ここまでのデータの流れを整理すると、次のようになります。
作品一覧
↓
MoviePosterCard(movie: movie)
↓
MovieDetailPage(movie: movie)
↓
Play Trailerボタンを押す
↓
YouTubePlayerPage(movie: movie)
↓
movie.youtubeVideoIdで動画を再生する
この流れがとても大切です。
YouTube再生画面は、自分で「どの動画を再生するか」を決めているわけではありません。
前の画面から渡された movie の中にある youtubeVideoId を見て、再生する動画を決めています。
youtube_player_iframeを使う準備
YouTubeをアプリ内で再生するために、youtube_player_iframe を使います。
pubspec.yaml には、次のように書いてあります。
dependencies:
flutter:
sdk: flutter
youtube_player_iframe: ^5.2.2
このパッケージを使うことで、Flutterアプリの中にYouTubeプレイヤーを表示できます。
パッケージを追加したら、ターミナルで次のコマンドを実行します。
flutter pub get
これで、Flutterプロジェクトにパッケージが読み込まれます。
main.dartでimportする
youtube_player_iframe を使うために、main.dart の上部でimportしています。
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
このimportがないと、YoutubePlayerController や YoutubePlayer が使えません。
もし次のようなエラーが出た場合は、importが入っているか確認してください。
Undefined class 'YoutubePlayerController'
Undefined name 'YoutubePlayer'
YouTubePlayerPageのStateクラス
YouTubePlayerPage の状態は、_YouTubePlayerPageState で管理しています。
class _YouTubePlayerPageState extends State<YouTubePlayerPage> {
late final YoutubePlayerController controller;
ここでは、YoutubePlayerController というものを持っています。
late final YoutubePlayerController controller;
この controller が、YouTubeプレイヤーを操作するための中心になります。
Controllerとは?
controller は、プレイヤーを操作するためのリモコンのようなものです。
YouTubeプレイヤーに対して、次のような指示を出すために使います。
どの動画を読み込むか
自動再生するか
ミュートするか
プレイヤーの設定をどうするか
Flutterでは、動画プレイヤー、テキスト入力、スクロールなど、何かを操作するときに Controller という名前のクラスがよく出てきます。
今回の場合は、YouTube動画を操作するための YoutubePlayerController を使います。
late finalとは?
controller には、late final がついています。
late final YoutubePlayerController controller;
これは、少し分けて考えると分かりやすいです。
| 書き方 | 意味 |
|---|---|
late | あとで必ず値を入れる |
final | 一度入れたら変更しない |
つまり、late final は次のような意味です。
今すぐは値を入れない
でもあとで必ず入れる
一度入れたら別のcontrollerには変えない
controller は、initState の中で作ります。
initStateでControllerを作る
YouTubeプレイヤーのControllerは、initState の中で作っています。
@override
void initState() {
super.initState();
controller = YoutubePlayerController.fromVideoId(
videoId: widget.movie.youtubeVideoId,
autoPlay: true,
params: const YoutubePlayerParams(
showFullscreenButton: true,
playsInline: true,
strictRelatedVideos: true,
),
);
}
initState は、画面が作られるときに一度だけ実行される処理です。
ここで、再生したいYouTube動画IDを指定して、Controllerを作っています。
initStateとは?
initState は、StatefulWidget の画面が最初に作られるときに呼ばれるメソッドです。
@override
void initState() {
super.initState();
...
}
画面を表示する前に、最初の準備をしたいときに使います。
今回の場合は、YouTubeプレイヤーを表示する前に、Controllerを準備する必要があります。
YouTubePlayerPageが作られる
↓
initStateが呼ばれる
↓
YoutubePlayerControllerを作る
↓
画面にYoutubePlayerを表示する
動画プレイヤーの初期化のような処理は、initState に書くことが多いです。
super.initState()とは?
initState の最初には、次のコードがあります。
super.initState();
これは、親クラスの初期化処理を呼び出すためのものです。
Flutterの State クラスにも、もともとの初期化処理があります。
それをきちんと実行してから、自分の初期化処理を書くイメージです。
Flutter側の初期化
↓
自分で書いたcontrollerの準備
initState を書くときは、基本的に super.initState(); を入れると覚えておきましょう。
fromVideoIdで動画IDを指定する
Controllerは、fromVideoId で作っています。
controller = YoutubePlayerController.fromVideoId(
videoId: widget.movie.youtubeVideoId,
autoPlay: true,
params: const YoutubePlayerParams(
showFullscreenButton: true,
playsInline: true,
strictRelatedVideos: true,
),
);
ここで一番大事なのは、この部分です。
videoId: widget.movie.youtubeVideoId,
詳細画面から渡された movie の中にある youtubeVideoId を使っています。
これにより、作品ごとに違うYouTube動画を再生できます。
widget.movie.youtubeVideoIdとは?
YouTubePlayerPage は、MovieItem movie を受け取っています。
final MovieItem movie;
State クラスの中では、widget.movie と書くことで、その作品データにアクセスできます。
widget.movie
さらに、その中の youtubeVideoId を使うので、次のように書きます。
widget.movie.youtubeVideoId
つまり、これは次の意味です。
このYouTubePlayerPageに渡された作品データの中の動画ID
このIDを YoutubePlayerController に渡して、動画を読み込んでいます。
autoPlayで自動再生する
Controllerには、次の指定があります。
autoPlay: true,
これは、画面を開いたら自動で動画を再生する指定です。
YouTubePlayerPageを開く
↓
動画が自動で再生される
自動再生したくない場合は、次のようにします。
autoPlay: false,
授業や教材では、どちらでも構いません。
動画アプリ風にしたい場合は、autoPlay: true の方が雰囲気が出ます。
YoutubePlayerParamsとは?
YoutubePlayerParams は、YouTubeプレイヤーの細かい設定をまとめるためのものです。
params: const YoutubePlayerParams(
showFullscreenButton: true,
playsInline: true,
strictRelatedVideos: true,
),
ここでは、次の3つを指定しています。
| 設定 | 内容 |
|---|---|
showFullscreenButton | 全画面ボタンを表示する |
playsInline | 画面内で再生する |
strictRelatedVideos | 関連動画をなるべく同じチャンネル内に制限する |
この設定によって、アプリ内で扱いやすいプレイヤーになります。
showFullscreenButton
次の指定は、全画面ボタンを表示する設定です。
showFullscreenButton: true,
true にすると、YouTubeプレイヤーに全画面表示のボタンが出ます。
動画を通常表示
↓
全画面ボタンを押す
↓
画面いっぱいで再生
スマホで動画を見る場合、全画面表示できると便利です。
playsInline
次の指定は、動画をアプリ画面内で再生する設定です。
playsInline: true,
playsInline を true にすると、動画がアプリの中でそのまま再生されやすくなります。
動画アプリ風のUIでは、画面の中で自然に再生される方が使いやすいです。
strictRelatedVideos
次の指定は、関連動画に関する設定です。
strictRelatedVideos: true,
YouTubeでは、動画が終わったあとに関連動画が表示されることがあります。
strictRelatedVideos: true にすると、関連動画の表示をある程度制御しやすくなります。
完全に思い通りにできるわけではありませんが、教材アプリとしては入れておくとよい設定です。
ここまでのまとめ
ここまでで、YouTube再生画面の準備部分を確認しました。
大切なポイントは次の通りです。
- YouTube再生画面は
YouTubePlayerPageで作る。 YouTubePlayerPageはMovieItem movieを受け取る。- 作品ごとに違う動画を再生するために、
movie.youtubeVideoIdを使う。 youtube_player_iframeを使うには、pubspec.yamlに追加する。main.dartでyoutube_player_iframeをimportする。YoutubePlayerControllerは、YouTubeプレイヤーを操作するためのController。late finalは、あとで必ず値を入れて、その後は変更しないという意味。initStateは、画面が作られるときに一度だけ実行される。YoutubePlayerController.fromVideoIdで、再生する動画IDを指定する。autoPlay: trueにすると、画面を開いたときに自動再生できる。YoutubePlayerParamsで、全画面ボタンや画面内再生などの設定ができる。
buildでYouTubeプレイヤーを表示する
ここからは、実際に画面へYouTubeプレイヤーを表示する部分を見ていきます。
YouTubePlayerPage の build は、次のような構造になっています。
@override
Widget build(BuildContext context) {
return YoutubePlayerScaffold(
controller: controller,
builder: (context, player) {
return Scaffold(
backgroundColor: NetflixColors.black,
appBar: AppBar(
backgroundColor: NetflixColors.black,
surfaceTintColor: NetflixColors.black,
title: Text(
widget.movie.title,
style: const TextStyle(
color: NetflixColors.white,
fontWeight: FontWeight.w900,
),
),
),
body: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: player,
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(18),
child: ListView(
children: [
Text(
widget.movie.title,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 24,
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 12),
MetaLine(movie: widget.movie),
const SizedBox(height: 18),
Text(
widget.movie.description,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 14,
height: 1.45,
),
),
],
),
),
),
],
),
);
},
);
}
この画面では、上にYouTubeプレイヤーを表示し、その下に作品タイトルや説明文を表示しています。
YouTubeプレイヤー
↓
作品タイトル
↓
メタ情報
↓
説明文
YoutubePlayerScaffoldとは?
YoutubePlayerScaffold は、YouTubeプレイヤーを画面に表示するための土台です。
return YoutubePlayerScaffold(
controller: controller,
builder: (context, player) {
return Scaffold(
...
);
},
);
ここで大切なのは、controller を渡していることです。
controller: controller,
前半で作成した YoutubePlayerController を渡すことで、どの動画を再生するかが決まります。
そして、builder の中で player を受け取っています。
builder: (context, player) {
この player が、実際に画面に表示するYouTubeプレイヤーです。
playerとは?
builder の中に出てくる player は、YouTube動画を表示するWidgetです。
builder: (context, player) {
return Scaffold(
body: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: player,
),
],
),
);
},
この player を画面の中に置くことで、YouTube動画が表示されます。
つまり、流れとしてはこうです。
controllerで動画IDを指定する
↓
YoutubePlayerScaffoldにcontrollerを渡す
↓
builderでplayerを受け取る
↓
playerを画面に置く
↓
YouTube動画が表示される
AspectRatioで16:9にする
YouTubeプレイヤーは、AspectRatio で包んでいます。
AspectRatio(
aspectRatio: 16 / 9,
child: player,
),
AspectRatio は、縦横比を保って表示するためのWidgetです。
YouTube動画は、一般的に16:9の横長動画が多いです。
そのため、ここでは次のように指定しています。
aspectRatio: 16 / 9,
これにより、プレイヤーが自然な横長比率で表示されます。
なぜ16:9なのか
動画の多くは、横長の16:9で作られています。
たとえば、YouTubeやテレビの映像でもよく使われる比率です。
横:16
縦:9
もし比率を指定しないと、動画が縦に伸びたり、横に潰れたりすることがあります。
AspectRatio を使うことで、動画が自然な比率で表示されます。
きれいな横長動画
↓
見慣れたYouTube風の表示
Scaffoldで再生画面を作る
builder の中では、通常の Scaffold を返しています。
return Scaffold(
backgroundColor: NetflixColors.black,
appBar: AppBar(
...
),
body: Column(
...
),
);
背景色は、他の画面と同じように黒です。
backgroundColor: NetflixColors.black,
動画アプリ全体の世界観を統一するために、再生画面でも黒背景にしています。
AppBarに作品タイトルを表示する
再生画面の上部には、AppBarを表示しています。
appBar: AppBar(
backgroundColor: NetflixColors.black,
surfaceTintColor: NetflixColors.black,
title: Text(
widget.movie.title,
style: const TextStyle(
color: NetflixColors.white,
fontWeight: FontWeight.w900,
),
),
),
タイトルには、現在再生している作品名を表示しています。
widget.movie.title
たとえば、Squid Game のトレーラーを開いた場合、AppBarには次のように表示されます。
Squid Game
これにより、ユーザーは今どの作品の動画を見ているのか分かります。
surfaceTintColorとは?
AppBarには、次の指定も入っています。
surfaceTintColor: NetflixColors.black,
Material 3では、AppBarに自動で少し色味が乗ることがあります。
黒背景のデザインでは、その色味が少し気になる場合があります。
そこで、surfaceTintColor も黒にして、AppBarが余計に明るくならないようにしています。
背景も黒
AppBarも黒
余計な色味を出さない
Columnで動画と情報を縦に並べる
再生画面の本体は、Column で作っています。
body: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: player,
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(18),
child: ListView(
children: [
...
],
),
),
),
],
),
並びはこうです。
YouTubeプレイヤー
↓
作品情報
上に動画、下に説明文という構成です。
動画アプリとして、とても自然な画面構成です。
Expandedで下の情報エリアを広げる
YouTubeプレイヤーの下には、Expanded があります。
Expanded(
child: Padding(
padding: const EdgeInsets.all(18),
child: ListView(
children: [
...
],
),
),
),
Expanded は、残りのスペースを使って表示するためのWidgetです。
上部の動画プレイヤーは16:9で高さが決まります。
その下の残りスペースを、作品情報エリアとして使っています。
上:動画プレイヤー
下:残りのスペースに作品情報
Paddingで作品情報に余白を作る
作品情報エリアには、余白を入れています。
padding: const EdgeInsets.all(18),
これは、上下左右すべてに18の余白を入れる指定です。
文字が画面端にぴったりくっつくと読みにくくなります。
余白を入れることで、作品タイトルや説明文が読みやすくなります。
ListViewで説明文をスクロールできるようにする
作品情報エリアでは、ListView を使っています。
ListView(
children: [
Text(widget.movie.title),
const SizedBox(height: 12),
MetaLine(movie: widget.movie),
const SizedBox(height: 18),
Text(widget.movie.description),
],
),
説明文が長い場合、画面に収まりきらないことがあります。
ListView にしておくことで、下方向にスクロールできます。
作品タイトル
メタ情報
説明文
↓
長い場合はスクロール
このように、長くなる可能性がある情報には ListView を使うと安心です。
作品タイトルを表示する
動画の下には、作品タイトルを表示しています。
Text(
widget.movie.title,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 24,
fontWeight: FontWeight.w900,
),
),
widget.movie.title は、再生中の作品タイトルです。
文字サイズは 24、太さは w900 にしています。
fontSize: 24,
fontWeight: FontWeight.w900,
再生画面でも、作品タイトルは重要な情報なので、しっかり大きく表示しています。
MetaLineを再利用する
タイトルの下には、MetaLine を表示しています。
MetaLine(movie: widget.movie),
これは詳細画面でも使ったメタ情報のWidgetです。
年、年齢制限、カテゴリ、マッチ率などを表示します。
同じ部品を再利用することで、画面ごとの見た目に統一感が出ます。
詳細画面でもMetaLine
再生画面でもMetaLine
↓
アプリ全体の見た目がそろう
部品化しておくと、こういう再利用がしやすくなります。
説明文を表示する
最後に、作品説明文を表示しています。
Text(
widget.movie.description,
style: const TextStyle(
color: NetflixColors.white,
fontSize: 14,
height: 1.45,
),
),
widget.movie.description には、作品データの説明文が入っています。
行間は height: 1.45 です。
height: 1.45,
説明文は複数行になることがあるので、少し行間を広げて読みやすくしています。
disposeでControllerを閉じる
YouTubeプレイヤーでは、画面を閉じるときの処理も大切です。
コードでは、次のように dispose を書いています。
@override
void dispose() {
controller.close();
super.dispose();
}
dispose は、画面が破棄されるときに呼ばれるメソッドです。
YouTubeプレイヤーのControllerは、使い終わったら閉じる必要があります。
controller.close();
これを書いておくことで、不要な処理が残り続けるのを防げます。
なぜcontroller.closeが必要なのか
動画プレイヤーは、画面を閉じたあとも内部で処理が残ることがあります。
たとえば、Controllerを閉じないと、次のような問題につながることがあります。
画面を閉じたのに動画処理が残る
同じ画面を何度も開いて動作が重くなる
メモリを余計に使う
そこで、画面を閉じるタイミングで controller.close() を実行します。
controller.close();
これは、使い終わったリモコンをきちんと片付けるようなイメージです。
super.dispose()も忘れない
dispose の最後には、次のコードがあります。
super.dispose();
これは、Flutter側の終了処理を呼び出すためのものです。
initState で super.initState() を呼んだように、dispose でも super.dispose() を呼びます。
自分で作ったcontrollerを閉じる
↓
Flutter側の終了処理を実行する
基本的には、dispose を書くときは最後に super.dispose(); を入れると覚えておきましょう。
よくあるつまずきポイント
Q. YouTubeプレイヤーが表示されません。
まず、pubspec.yaml にパッケージが入っているか確認してください。
youtube_player_iframe: ^5.2.2
そのあと、ターミナルで次のコマンドを実行します。
flutter pub get
さらに、main.dart の上部にimportがあるか確認してください。
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
Q. 動画が違う作品になってしまいます。
videoId に、正しい作品の動画IDが渡されているか確認してください。
videoId: widget.movie.youtubeVideoId,
固定の動画IDを書いてしまうと、どの作品を開いても同じ動画が再生されます。
作品ごとに違う動画を再生したい場合は、widget.movie.youtubeVideoId を使います。
Q. Play Trailerボタンを押しても画面が開きません。
詳細画面側で、YouTubePlayerPage へ移動するコードがあるか確認してください。
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => YouTubePlayerPage(movie: movie),
),
);
また、YouTubePlayerPage に movie を渡しているかも確認しましょう。
Q. 画面を閉じても音が残るように感じます。
dispose でControllerを閉じているか確認してください。
@override
void dispose() {
controller.close();
super.dispose();
}
動画や音声を扱う画面では、終了処理がとても大切です。
チャレンジ
チャレンジ1:自動再生をOFFにしよう
次のコードを探してください。
autoPlay: true,
これを次のように変更します。
autoPlay: false,
再生画面を開いたときに、自動再生されなくなるか確認してください。
チャレンジ2:動画下のタイトル文字を少し大きくしよう
次のコードを探してください。
fontSize: 24,
これを次のように変更します。
fontSize: 28,
動画下の作品タイトルが大きくなるか確認してください。
チャレンジ3:説明文の行間を広げよう
次のコードを探してください。
height: 1.45,
これを次のように変更します。
height: 1.65,
説明文が読みやすくなるか確認してください。
チャレンジ4:AppBarのタイトルを日本語風にしてみよう
次のコードを探してください。
title: Text(
widget.movie.title,
これを次のように変更します。
title: Text(
'${widget.movie.title} の予告編',
AppBarに「作品名 の予告編」と表示されるか確認してください。
チャレンジの答え
チャレンジ1の答え
変更前:
autoPlay: true,
変更後:
autoPlay: false,
再生画面を開いても、自動再生されなくなります。
チャレンジ2の答え
変更前:
fontSize: 24,
変更後:
fontSize: 28,
動画下の作品タイトルが少し大きくなります。
チャレンジ3の答え
変更前:
height: 1.45,
変更後:
height: 1.65,
説明文の行間が広がり、少し読みやすくなります。
チャレンジ4の答え
変更前:
title: Text(
widget.movie.title,
変更後:
title: Text(
'${widget.movie.title} の予告編',
AppBarのタイトルに「作品名 の予告編」と表示されます。
この節のまとめ
この節では、youtube_player_iframe を使って、作品トレーラーをアプリ内で再生する方法を学びました。
大切なポイントは次の通りです。
- YouTube再生画面は
YouTubePlayerPageで作る。 - 作品ごとに違う動画を再生するために、
MovieItemのyoutubeVideoIdを使う。 YoutubePlayerControllerは、YouTubeプレイヤーを操作するためのController。initStateでControllerを作る。YoutubePlayerController.fromVideoIdで再生する動画IDを指定する。autoPlayで自動再生するかどうかを決められる。YoutubePlayerParamsで、全画面ボタンなどの設定ができる。YoutubePlayerScaffoldにControllerを渡す。builderの中で受け取ったplayerを画面に表示する。AspectRatioを使うと、動画を16:9で表示できる。- 再生画面でも、作品タイトルや説明文を表示できる。
disposeでcontroller.close()を呼び、使い終わったControllerを片付ける。
次のステップ
次の節では、作品を共有する Share ボタンを学びます。
share_plus を使って、作品タイトルやYouTubeリンクを共有する方法を確認します。
iOSで共有メニューを安定して表示するための sharePositionOrigin も、あわせて見ていきましょう。