
methodで動画データに表示用のふるまいを持たせる
この節で学ぶこと
前回の 3-4 では、constructor と property を使って、動画データの持ち物を決める方法を学びました。
たとえば、YouTube風アプリで使う Video classには、次のようなpropertyがありました。
class Video {
const Video({
required this.title,
required this.channelName,
required this.views,
required this.publishedAt,
required this.duration,
required this.category,
required this.thumbnailColor,
required this.channelColor,
required this.isLive,
});
final String title;
final String channelName;
final int views;
final String publishedAt;
final String duration;
final String category;
final Color thumbnailColor;
final Color channelColor;
final bool isLive;
}
ここまでで、動画1本分の情報をまとめて持てるようになりました。
しかし、実際のアプリでは、データをそのまま表示するだけでは足りないことがあります。
たとえば、再生回数が 128000 という数字で保存されているとします。
でも、画面には次のように表示したいです。
12.8万回視聴
また、通常動画なら、
12.8万回視聴・2日前
と表示したいです。
一方で、ライブ配信中の動画なら、
ライブ配信中
と表示したいです。
このように、保存しているデータを、画面に出しやすい形へ変えるときに使うのが method や getter です。
この節のゴール
この節のゴールは、Video classの中に、表示用のふるまいを持たせる考え方を理解することです。
最終的には、完成アプリで使っている次のコードが読めるようになることを目指します。
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
このコードを初めて見ると、少し難しく感じるかもしれません。
でも、やっていることはとてもシンプルです。
再生回数の数字を、画面に出しやすい文字へ変える。
ライブ中なら、表示する文章を切り替える。
この節で大切なのは、次の一文です。
methodは、データに「できること」を持たせる仕組みである。
まずmethodとは何か
method とは、classの中に書く関数のようなものです。
関数は、処理をまとめるために使いました。
methodも似ています。
ただし、methodはclassの中に書きます。
たとえば、Video classの中に、動画の説明文を作るmethodを書いてみます。
class Video {
const Video({
required this.title,
required this.channelName,
});
final String title;
final String channelName;
String description() {
return '$title / $channelName';
}
}
この中の次の部分がmethodです。
String description() {
return '$title / $channelName';
}
これは、次の意味です。
titleとchannelNameを使って、動画の説明文を作る。
実際に使うと、次のようになります。
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
channelName: 'Code Studio',
);
print(video.description());
}
class Video {
const Video({
required this.title,
required this.channelName,
});
final String title;
final String channelName;
String description() {
return '$title / $channelName';
}
}
出力結果です。
FlutterでYouTube風UIを作る / Code Studio
video.description() と書くと、Video の中にある description というmethodが実行されます。
propertyとmethodの違い
ここで、propertyとmethodの違いを整理します。
| 種類 | 役割 | YouTube風アプリでの例 |
|---|---|---|
| property | データそのものを持つ | title、views、publishedAt |
| method | データを使って処理する | 表示用テキストを作る |
| getter | methodに近いが、propertyのように取り出せる | viewLabel、metaLabel |
たとえば、views はpropertyです。
final int views;
これは、再生回数そのものを持っています。
一方で、viewLabel は表示用の文字を作ります。
String get viewLabel {
return '$views回視聴';
}
views は元データ。
viewLabel は画面に出すための表示用データです。
views:
128000
viewLabel:
128000回視聴
なぜmethodが必要なのか
動画データには、再生回数を数字として持たせます。
final int views;
たとえば、次のような値です。
128000
8500
24000
しかし、画面にそのまま出すと、少し不自然です。
128000
8500
24000
YouTube風の画面なら、次のように表示したいです。
12.8万回視聴
8500回視聴
2.4万回視聴
つまり、データとして持つ値と、画面に表示する文字は少し違います。
| 元データ | 表示したい文字 |
|---|---|
| 128000 | 12.8万回視聴 |
| 8500 | 8500回視聴 |
| 24000 | 2.4万回視聴 |
この変換を毎回UI側に書くと、コードが読みにくくなります。
そこで、Video classの中に「表示用の文字を作る処理」を持たせます。
これがmethodやgetterの出番です。
まずは単純なmethodを書いてみる
最初は、再生回数に「回視聴」をつけるだけのmethodを書いてみます。
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
);
print(video.createViewLabel());
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String createViewLabel() {
return '$views回視聴';
}
}
出力結果です。
128000回視聴
ここで大事なのは、views は数字として持っていることです。
final int views;
そして、表示するときだけ、文字に変えています。
return '$views回視聴';
このように、methodを使うと、データを表示用に整える処理をclassの中にまとめられます。
methodの書き方を分解する
次のmethodを分解して見ます。
String createViewLabel() {
return '$views回視聴';
}
| 部分 | 意味 |
|---|---|
String | このmethodは文字列を返す |
createViewLabel | methodの名前 |
() | 今回は追加の材料を受け取らない |
{ } | 処理を書く場所 |
return | 結果を返す |
'$views回視聴' | 作りたい文字 |
つまり、このmethodは次のように読めます。
createViewLabelという処理を実行すると、
viewsに「回視聴」をつけた文字を返す。
使うときは、次のように書きます。
video.createViewLabel()
これは、次の意味です。
videoの中にあるcreateViewLabelを実行する
getterとは何か
完成アプリでは、methodではなく getter を使っています。
String get viewLabel {
return '$views回視聴';
}
getter は、methodのように処理を書けます。
でも、使うときはpropertyのように書けます。
methodの場合です。
video.createViewLabel()
getterの場合です。
video.viewLabel
見た目が少し違います。
| 種類 | 定義 | 使い方 |
|---|---|---|
| method | String createViewLabel() | video.createViewLabel() |
| getter | String get viewLabel | video.viewLabel |
初心者向けには、まず次の理解で大丈夫です。
getterは、計算して作るpropertyのようなもの。
つまり、viewLabel は実際に保存している値ではありません。
views から、その場で作っている表示用の値です。
getterで再生回数ラベルを作る
getterを使って、再生回数の表示用テキストを作ってみます。
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
);
print(video.viewLabel);
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String get viewLabel {
return '$views回視聴';
}
}
出力結果です。
128000回視聴
viewLabel はpropertyのように使えます。
video.viewLabel
でも、実際には中で処理をしています。
return '$views回視聴';
methodとgetterはどちらを使うべきか
初心者のうちは、厳密に使い分けすぎなくて大丈夫です。
ただし、今回のように「データから表示用の値を作るだけ」の場合は、getterが読みやすいです。
| やりたいこと | おすすめ |
|---|---|
| 再生回数を表示用テキストにする | getter |
| 投稿日と再生回数をまとめた文字を作る | getter |
| 何かを実行する処理を書く | method |
| 外から値を受け取って計算する | method |
たとえば、完成アプリの viewLabel や metaLabel は、値を取り出しているように見えるため、getterにしています。
video.viewLabel
video.metaLabel
UI側から見ると、とても読みやすくなります。
再生回数を「万回視聴」に変える
ここから、完成アプリに近づけます。
再生回数が10000以上なら、万回視聴 にしたいとします。
128000 → 12.8万回視聴
24000 → 2.4万回視聴
8500 → 8500回視聴
まず、考え方を日本語で書きます。
もし views が 10000 以上なら、
views を 10000 で割って、「万回視聴」をつける。
そうでなければ、
そのまま「回視聴」をつける。
これをDartで書くと、次のようになります。
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
少し長く見えますが、分解すれば大丈夫です。
if文で表示を切り替える
まず、if の部分を見ます。
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
これは、次の意味です。
もし再生回数が10000以上なら、
万回視聴の形で返す。
views >= 10000 は条件です。
| 条件 | 意味 |
|---|---|
views >= 10000 | viewsが10000以上 |
views < 10000 | viewsが10000未満 |
たとえば、views が 128000 なら、10000以上なので、ifの中が実行されます。
views が 8500 なら、10000未満なので、ifの中は実行されません。
views / 10000 の意味
次の部分を見ます。
views / 10000
これは、再生回数を10000で割っています。
たとえば、
128000 / 10000 = 12.8
24000 / 10000 = 2.4
これで、「何万回か」を出しています。
| views | views / 10000 |
|---|---|
| 128000 | 12.8 |
| 24000 | 2.4 |
| 10000 | 1.0 |
この数字に 万回視聴 をつければ、YouTube風の表示に近づきます。
toStringAsFixed(1) の意味
次に、この部分です。
.toStringAsFixed(1)
これは、小数点以下を1桁にそろえて文字に変える処理です。
たとえば、次のようになります。
| 数字 | toStringAsFixed(1) |
|---|---|
| 12.8 | 12.8 |
| 2.4 | 2.4 |
| 1 | 1.0 |
今回の表示では、12.8万回視聴 のようにしたいので、小数1桁の文字にしています。
完成アプリでは、次のように使っています。
'${(views / 10000).toStringAsFixed(1)}万回視聴'
これは、次のように読めます。
viewsを10000で割る。
小数1桁の文字にする。
その後ろに「万回視聴」をつける。
まずはDartPadで試すコード
ここまでの内容を、Dartだけで試せるコードにします。
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
);
print(video.title);
print(video.viewLabel);
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
}
出力結果です。
FlutterでYouTube風UIを作る
12.8万回視聴
ここで確認することは、次の3つです。
viewsは128000という数字で持っている。
viewLabelは12.8万回視聴という文字を作る。
元データと表示用テキストを分けている。
複数の動画で試す
次に、複数の動画で試してみます。
void main() {
final videos = [
Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
),
Video(
title: 'DartのListとMapを解説',
views: 8500,
),
Video(
title: 'UIデザインの基本',
views: 24000,
),
];
for (final video in videos) {
print('${video.title} / ${video.viewLabel}');
}
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
}
出力結果です。
FlutterでYouTube風UIを作る / 12.8万回視聴
DartのListとMapを解説 / 8500回視聴
UIデザインの基本 / 2.4万回視聴
同じ viewLabel を使っているのに、動画ごとの再生回数に合わせて表示が変わっています。
これが、classにふるまいを持たせる便利さです。
ここまでの整理
| 元データ | getter | 表示結果 |
|---|---|---|
views: 128000 | viewLabel | 12.8万回視聴 |
views: 8500 | viewLabel | 8500回視聴 |
views: 24000 | viewLabel | 2.4万回視聴 |
views は、計算しやすいように数字で持ちます。
viewLabel は、画面に出しやすいように文字で作ります。
データとして持つもの:
views
画面に出すために作るもの:
viewLabel
1億回以上にも対応する
完成アプリでは、1億回以上の再生回数にも対応しています。
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
条件が2つあります。
| 条件 | 表示 |
|---|---|
views >= 100000000 | 億回視聴 |
views >= 10000 | 万回視聴 |
| それ以外 | 回視聴 |
この順番も重要です。
先に1億以上かどうかを確認します。
そのあと、1万以上かどうかを確認します。
条件の順番に注意する
もし、先に1万以上を確認してしまうと、1億以上の動画もそこで止まってしまいます。
悪い例です。
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
return '$views回視聴';
}
この場合、views が 120000000 でも、最初の views >= 10000 に当てはまってしまいます。
そのため、億回視聴 の判定まで進みません。
だから、大きい条件から先に書きます。
1億以上か確認
↓
1万以上か確認
↓
それ以外
この考え方は、プログラミングでとても大切です。
前半のまとめ
この前半では、method と getter の基本を学びました。
大切なポイントは、次の通りです。
- methodは、classの中に書く処理である
- getterは、計算して作るpropertyのように使える
- viewsは数字として持つ
- viewLabelは、画面に表示する文字として作る
- 10000以上なら「万回視聴」に変換できる
- 条件分岐では、判定する順番が大切
YouTube風アプリでは、動画データをそのまま表示するだけではありません。
views のような元データを、viewLabel のような表示用テキストに変換して使います。
metaLabelを作る
前半では、views という数字から、viewLabel という表示用テキストを作りました。
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
これで、次のような表示が作れます。
128000 → 12.8万回視聴
8500 → 8500回視聴
24000 → 2.4万回視聴
しかし、YouTube風の動画カードでは、再生回数だけではなく、投稿日も一緒に表示したいです。
たとえば、次のような表示です。
12.8万回視聴・2日前
このような、再生回数と投稿日をまとめた表示用テキストを metaLabel として作ります。
metaLabelとは何か
metaLabel は、動画タイトルの下に表示する補足情報のようなものです。
完成アプリでは、動画カードの下に次のような情報が表示されます。
Code Studio
12.8万回視聴・2日前
このうち、下の行が metaLabel です。
12.8万回視聴・2日前
元になるデータは、次の2つです。
| 元データ | 意味 |
|---|---|
viewLabel | 再生回数を表示用にした文字 |
publishedAt | 投稿日 |
この2つを組み合わせて、metaLabel を作ります。
String get metaLabel {
return '$viewLabel・$publishedAt';
}
これは、次のように読めます。
viewLabelとpublishedAtをつなげて、動画の補足情報を作る。
metaLabelをDartPadで試す
まずは、ライブ判定なしのシンプルな形で試します。
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
publishedAt: '2日前',
);
print(video.title);
print(video.viewLabel);
print(video.metaLabel);
}
class Video {
const Video({
required this.title,
required this.views,
required this.publishedAt,
});
final String title;
final int views;
final String publishedAt;
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
return '$viewLabel・$publishedAt';
}
}
出力結果です。
FlutterでYouTube風UIを作る
12.8万回視聴
12.8万回視聴・2日前
ここで大切なのは、metaLabel の中で viewLabel を使っていることです。
return '$viewLabel・$publishedAt';
つまり、getterの中で、別のgetterを使うこともできます。
viewLabelとmetaLabelの関係
viewLabel と metaLabel の役割を整理します。
| getter | 役割 | 表示例 |
|---|---|---|
viewLabel | 再生回数だけを表示用にする | 12.8万回視聴 |
metaLabel | 再生回数と投稿日をまとめる | 12.8万回視聴・2日前 |
流れとしては、こうです。
views
↓
viewLabel
↓
metaLabel
もう少し具体的に見ると、次のようになります。
128000
↓
12.8万回視聴
↓
12.8万回視聴・2日前
このように、元データを少しずつ画面用の文字に整えていきます。
ライブ配信の場合を考える
完成アプリには、通常動画だけでなく、ライブ配信中の動画もあります。
たとえば、次のような動画です。
Video(
title: 'ライブ:Flutter質問会|Widget・ListView・classの疑問を解決',
channelName: 'Mobile Dev Live',
views: 5600,
publishedAt: '現在',
duration: 'LIVE',
category: 'LIVE',
isLive: true,
)
この動画はライブ配信中なので、普通の動画のように、
5600回視聴・現在
と出すよりも、
ライブ配信中
と表示したほうが自然です。
つまり、isLive の値によって表示を切り替えます。
| isLive | 表示したいmetaLabel |
|---|---|
true | ライブ配信中 |
false | 12.8万回視聴・2日前 |
isLiveで表示を切り替える
isLive は bool 型です。
true または false のどちらかを持ちます。
final bool isLive;
metaLabel の中で、この isLive を使って条件分岐します。
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
これは、次のように読めます。
もしライブ配信中なら、「ライブ配信中」と返す。
そうでなければ、再生回数と投稿日をつなげて返す。
if (isLive) は、次の意味です。
isLiveがtrueなら
つまり、
if (isLive) {
return 'ライブ配信中';
}
は、
ライブ中なら、この時点で「ライブ配信中」を返して終わる。
という意味です。
ライブ表示をDartPadで試す
通常動画とライブ動画を比べてみます。
void main() {
final normalVideo = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
publishedAt: '2日前',
isLive: false,
);
final liveVideo = Video(
title: 'ライブ:Flutter質問会',
views: 5600,
publishedAt: '現在',
isLive: true,
);
print(normalVideo.title);
print(normalVideo.metaLabel);
print('---');
print(liveVideo.title);
print(liveVideo.metaLabel);
}
class Video {
const Video({
required this.title,
required this.views,
required this.publishedAt,
required this.isLive,
});
final String title;
final int views;
final String publishedAt;
final bool isLive;
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
}
出力結果です。
FlutterでYouTube風UIを作る
12.8万回視聴・2日前
---
ライブ:Flutter質問会
ライブ配信中
同じ metaLabel を使っているのに、isLive の値によって表示が変わっています。
ここが、getterにふるまいを持たせる面白いところです。
なぜUI側に直接書かないのか
ここで、疑問が出るかもしれません。
「表示を切り替えるなら、画面側で直接書けばよいのでは?」
たしかに、それもできます。
たとえば、Flutterの画面側で次のように書くこともできます。
Text(
video.isLive
? 'ライブ配信中'
: '${video.viewLabel}・${video.publishedAt}',
)
しかし、画面側にこのような処理が増えると、UIコードが読みにくくなります。
画面側では、本来は「何を表示するか」をできるだけシンプルに書きたいです。
Text(video.metaLabel)
このように書けると、かなり読みやすくなります。
| 書き方 | 読みやすさ |
|---|---|
Text(video.isLive ? 'ライブ配信中' : '${video.viewLabel}・${video.publishedAt}') | 条件が混ざっていて少し読みにくい |
Text(video.metaLabel) | 何を表示するかが分かりやすい |
そのため、表示用のルールは Video classの中にまとめておくと便利です。
データ側にふるまいを持たせる考え方
ここまでで、Video classには2種類のものが入っていることが分かります。
1つ目は、元データです。
final String title;
final int views;
final String publishedAt;
final bool isLive;
2つ目は、元データから作る表示用の値です。
String get viewLabel { ... }
String get metaLabel { ... }
整理すると、次のようになります。
| 種類 | 例 | 役割 |
|---|---|---|
| property | views | 元データを持つ |
| getter | viewLabel | 元データを表示用に変える |
| getter | metaLabel | 複数の元データから表示文を作る |
このように、classには「持ち物」だけでなく、「ふるまい」も持たせることができます。
Videoは、viewsを持っている。
Videoは、viewsを使ってviewLabelを作れる。
Videoは、isLiveを見てmetaLabelを切り替えられる。
これが、methodで動画データに表示用のふるまいを持たせる という意味です。
完成アプリのVideo classに近づける
完成アプリの Video classは、次のようになっていました。
class Video {
const Video({
required this.title,
required this.channelName,
required this.views,
required this.publishedAt,
required this.duration,
required this.category,
required this.thumbnailColor,
required this.channelColor,
required this.isLive,
});
final String title;
final String channelName;
final int views;
final String publishedAt;
final String duration;
final String category;
final Color thumbnailColor;
final Color channelColor;
final bool isLive;
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
}
これを大きく分けると、次の3つです。
| 部分 | 役割 |
|---|---|
| constructor | Video を作るときに値を受け取る |
| property | 動画の元データを持つ |
| getter | 画面に表示しやすい文字を作る |
つまり、Video classは、ただの入れ物ではありません。
画面表示に必要な小さな処理も持っています。
VideoInfoではmetaLabelを使う
完成アプリの VideoInfo では、次のように metaLabel を使っています。
Text(
video.metaLabel,
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
ここでは、video.metaLabel と書くだけで、通常動画とライブ動画の表示を切り替えられます。
通常動画なら、
12.8万回視聴・2日前
ライブ動画なら、
ライブ配信中
になります。
UI側のコードは、細かい条件を知る必要がありません。
Video classが、表示用の文字を用意してくれているからです。
Thumbnailではdurationを使う
完成アプリでは、サムネイル右下に動画時間を表示しています。
通常動画なら、次のような表示です。
12:34
08:21
15:10
この表示には、duration propertyを使います。
Text(video.duration)
一方、ライブ配信の場合は、duration に LIVE を入れています。
duration: 'LIVE',
さらに、画面側では isLive を使って、赤い「ライブ」ラベルを出す処理もできます。
isLiveがtrue
↓
赤いライブ表示
isLiveがfalse
↓
黒い動画時間表示
ここでも、Video のpropertyがUIに使われています。
methodとgetterの考え方をもう一度整理する
ここで、methodとgetterの違いをもう一度整理します。
method
methodは、処理を実行する形です。
String createViewLabel() {
return '$views回視聴';
}
使うときは、丸かっこをつけます。
video.createViewLabel()
getter
getterは、処理を書けますが、propertyのように取り出せます。
String get viewLabel {
return '$views回視聴';
}
使うときは、丸かっこをつけません。
video.viewLabel
今回のように「表示用の値を取り出したい」場合は、getterが自然です。
手を動かす練習1:単純なviewLabelを作る
まず、再生回数に「回視聴」をつけるだけのgetterを書いてください。
解答例
void main() {
final video = Video(
title: 'Dartのmethod入門',
views: 8500,
);
print(video.viewLabel);
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String get viewLabel {
return '$views回視聴';
}
}
出力結果です。
8500回視聴
手を動かす練習2:10000以上なら万回視聴にする
次に、10000以上なら 万回視聴 に変換してください。
解答例
void main() {
final video = Video(
title: 'UIデザインの基本',
views: 24000,
);
print(video.viewLabel);
}
class Video {
const Video({
required this.title,
required this.views,
});
final String title;
final int views;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
}
出力結果です。
2.4万回視聴
手を動かす練習3:metaLabelを作る
viewLabel と publishedAt を使って、metaLabel を作ってください。
解答例
void main() {
final video = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
publishedAt: '2日前',
);
print(video.metaLabel);
}
class Video {
const Video({
required this.title,
required this.views,
required this.publishedAt,
});
final String title;
final int views;
final String publishedAt;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
return '$viewLabel・$publishedAt';
}
}
出力結果です。
12.8万回視聴・2日前
手を動かす練習4:isLiveで表示を切り替える
isLive が true のときは ライブ配信中、false のときは 再生回数・投稿日 を表示してください。
解答例
void main() {
final normalVideo = Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
publishedAt: '2日前',
isLive: false,
);
final liveVideo = Video(
title: 'ライブ:Flutter質問会',
views: 5600,
publishedAt: '現在',
isLive: true,
);
print(normalVideo.metaLabel);
print(liveVideo.metaLabel);
}
class Video {
const Video({
required this.title,
required this.views,
required this.publishedAt,
required this.isLive,
});
final String title;
final int views;
final String publishedAt;
final bool isLive;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
}
出力結果です。
12.8万回視聴・2日前
ライブ配信中
手を動かす練習5:複数動画でmetaLabelを表示する
複数の動画をListに入れて、タイトルと metaLabel を表示してください。
解答例
void main() {
final videos = [
Video(
title: 'FlutterでYouTube風UIを作る',
views: 128000,
publishedAt: '2日前',
isLive: false,
),
Video(
title: 'DartのListとMapを解説',
views: 8500,
publishedAt: '5日前',
isLive: false,
),
Video(
title: 'ライブ:Flutter質問会',
views: 5600,
publishedAt: '現在',
isLive: true,
),
];
for (final video in videos) {
print('${video.title} / ${video.metaLabel}');
}
}
class Video {
const Video({
required this.title,
required this.views,
required this.publishedAt,
required this.isLive,
});
final String title;
final int views;
final String publishedAt;
final bool isLive;
String get viewLabel {
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
}
出力結果です。
FlutterでYouTube風UIを作る / 12.8万回視聴・2日前
DartのListとMapを解説 / 8500回視聴・5日前
ライブ:Flutter質問会 / ライブ配信中
このように、getterをclassの中に書いておくと、複数の動画でも同じルールで表示できます。
よくあるつまずき1:methodとgetterの違いが分からない
methodとgetterは似ています。
ただし、使うときの書き方が違います。
| 種類 | 定義 | 使い方 |
|---|---|---|
| method | String createViewLabel() | video.createViewLabel() |
| getter | String get viewLabel | video.viewLabel |
今回のように、表示用の値を取り出したいだけなら、getterが読みやすいです。
Text(video.metaLabel)
UI側では、このようにすっきり書けます。
よくあるつまずき2:returnの意味が分からない
getterやmethodでは、return が出てきます。
return '$views回視聴';
return は、「この結果を返す」という意味です。
たとえば、
String get viewLabel {
return '$views回視聴';
}
これは、次の意味です。
viewLabelを呼び出したら、
'$views回視聴' という文字を結果として返す。
return がないと、作った結果を外で使えません。
よくあるつまずき3:文字列の中に変数を入れる書き方
Dartでは、文字列の中に変数を入れるときに $ を使います。
return '$views回視聴';
これは、views の値を文字の中に入れています。
たとえば、views が 8500 なら、
8500回視聴
になります。
少し複雑な計算を入れるときは、${} を使います。
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
これは、次の意味です。
views / 10000 を計算する。
小数1桁にする。
その結果を文字列の中に入れる。
よくあるつまずき4:if文の順番を間違える
前半でも扱いましたが、1億回以上と1万回以上を判定するときは、大きい条件から書きます。
正しい例です。
String get viewLabel {
if (views >= 100000000) {
return '${(views / 100000000).toStringAsFixed(1)}億回視聴';
}
if (views >= 10000) {
return '${(views / 10000).toStringAsFixed(1)}万回視聴';
}
return '$views回視聴';
}
先に views >= 10000 を書くと、1億以上の数字もそこで当てはまってしまいます。
条件分岐は、順番も大切。
この考え方は、今後のプログラムでもよく使います。
よくあるつまずき5:UI側とデータ側の役割が混ざる
初心者は、画面側にすべての処理を書いてしまいがちです。
たとえば、次のような書き方です。
Text(
video.isLive
? 'ライブ配信中'
: '${video.viewLabel}・${video.publishedAt}',
)
これは動きます。
しかし、UI側が少し読みにくくなります。
そこで、Video class側に metaLabel を作ります。
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
すると、UI側はこう書けます。
Text(video.metaLabel)
画面側は表示に集中し、データ側で表示用の値を作る。
この分け方ができると、コードがかなり読みやすくなります。
完成アプリとのつながり
完成アプリの VideoInfo では、次のように metaLabel を表示します。
Text(
video.metaLabel,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: video.isLive ? Color(0xFFE62117) : Color(0xFF606060),
fontSize: 13,
fontWeight: video.isLive ? FontWeight.w700 : FontWeight.w400,
height: 1.25,
),
)
このコードの中で、表示する文字そのものは video.metaLabel が作っています。
通常動画なら、
12.8万回視聴・2日前
ライブ動画なら、
ライブ配信中
になります。
さらに、video.isLive を使って、文字色や太さも変えています。
isLiveがtrue
↓
赤く太い文字
isLiveがfalse
↓
グレーの通常文字
つまり、Video のデータとgetterが、UIの表示にそのままつながっています。
この節で覚える対応表
| やりたいこと | 使うもの | 例 |
|---|---|---|
| 再生回数の数字を持つ | property | views |
| 再生回数を表示用にする | getter | viewLabel |
| 投稿日と再生回数をまとめる | getter | metaLabel |
| ライブ中か判定する | bool | isLive |
| 表示を切り替える | if文 | if (isLive) |
| 結果を返す | return | return 'ライブ配信中'; |
| UIで表示する | Text | Text(video.metaLabel) |
確認問題1
method とは何ですか。
答え
classの中に書く処理です。
そのclassが持っているデータを使って、計算したり、表示用の文字を作ったりできます。
確認問題2
getter はどのように使いますか。
答え
propertyのように、丸かっこをつけずに使います。
video.viewLabel
viewLabel は保存された値ではなく、views から作られる表示用の値です。
確認問題3
次のコードは何をしていますか。
String get viewLabel {
return '$views回視聴';
}
答え
views の値に「回視聴」をつけて、表示用の文字を作っています。
たとえば、views が 8500 なら、8500回視聴 になります。
確認問題4
次のコードで、isLive が true のとき何が返りますか。
String get metaLabel {
if (isLive) {
return 'ライブ配信中';
}
return '$viewLabel・$publishedAt';
}
答え
ライブ配信中
が返ります。
確認問題5
なぜ metaLabel を Video classの中に作ると便利ですか。
答え
UI側で毎回条件分岐を書かなくてよくなるからです。
Text(video.metaLabel) と書くだけで、通常動画なら再生回数と投稿日、ライブ動画なら「ライブ配信中」を表示できます。
この節のまとめ
この節では、method と getter を使って、動画データに表示用のふるまいを持たせる方法を学びました。
views は、再生回数の元データです。
viewLabel は、views を画面に出しやすい文字へ変えたものです。
metaLabel は、動画の補足情報として表示する文字です。
通常動画なら、
12.8万回視聴・2日前
ライブ動画なら、
ライブ配信中
と表示できます。
この節のポイント:
- methodは、classの中に書く処理である
- getterは、計算して作るpropertyのように使える
- viewsは数字として持つ
- viewLabelは画面表示用の文字を作る
- metaLabelは再生回数・投稿日・ライブ状態を見て表示を切り替える
- UI側では Text(video.metaLabel) のようにシンプルに使える
大事なことは、
Video classは、動画のデータを持つだけでなく、画面に表示しやすい形へ整えるふるまいも持てる。
次の 3-6 では、final や getter の考え方をさらに使いながら、データを安全に扱うためのカプセル化を学びます。