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

【表示ラベル】statusLabel・priorityLabelで英語データを日本語表示に変換する

33LINE風チームタスク管理アプリを作りながら、ログイン・データベース・権限管理を学ぶ
FlutteriOSAndroidMacOSWindows基礎から学ぶ開発アプリ開発

このページでやること

このページでは、Firestoreに保存している英語データを、画面では日本語で表示できるようにします。

Firestoreには、次のように保存しています。

status: todo
priority: normal

でも、画面にそのまま出ると初心者には分かりにくいです。

todo
normal

そこで、画面では次のように変換します。

todo → 未対応
normal → 優先度:中

この変換に使うのが、次の2つです。

statusLabel()
priorityLabel()

今日のゴール

タスクカードに、分かりやすい日本語ラベルを表示します。

Firestoreの保存値
↓
todo / doing / done
low / normal / high

画面表示
↓
未対応 / 進行中 / 完了
優先度:低 / 優先度:中 / 優先度:高

このページで出てくる単語

単語一言説明
statusLabelステータスを日本語に変える関数
priorityLabel優先度を日本語に変える関数
statusタスクの進行状況
priorityタスクの優先度
switch値によって処理を分ける書き方
return結果を返す命令
defaultどれにも当てはまらない場合

関数とは、よく使う処理をまとめたものです。


npmや環境変数は必要?

このページでは、npmは使いません。

環境変数も設定しません。

やることは、main.dartTaskCard にある表示変換を確認・整理するだけです。

main.dartを開く
↓
TaskCardを探す
↓
statusLabelを作る
↓
priorityLabelを作る
↓
画面で確認する

Step 1:main.dartを開く

次のファイルを開きます。

lib/main.dart

ターミナルから開く場合はこちらです。

code lib/main.dart

code が使えない場合は、VS Codeの左側から lib/main.dart を開いてください。


Step 2:TaskCardを探す

main.dart の中で、次を検索します。

class TaskCard

VS Codeなら、次で検索できます。

command + F

TaskCard は、タスク1件分を表示する部品です。


Step 3:TaskCardが受け取る値を確認する

TaskCard の中に、次のような値があります。

final String status;
final String priority;

意味はこうです。

内容
statusFirestoreから取得した進行状況
priorityFirestoreから取得した優先度

Firestoreには、次のような英語データが入っています。

status: todo
priority: normal

このままだと画面に出したときに分かりにくいので、日本語に変えます。


Step 4:statusLabelを作る

TaskCard の中に、次の関数を追加します。

String statusLabel(String value) {
  switch (value) {
    case 'doing':
      return '進行中';
    case 'done':
      return '完了';
    case 'todo':
    default:
      return '未対応';
  }
}

これは、status の英語データを日本語に変える関数です。

変換ルールはこうです。

Firestoreの値画面表示
todo未対応
doing進行中
done完了

Step 5:statusLabelの意味

この部分を見ます。

case 'doing':
  return '進行中';

これは、valuedoing のとき、進行中 を返すという意味です。

次も同じです。

case 'done':
  return '完了';

valuedone のとき、完了 を返します。

最後はこれです。

case 'todo':
default:
  return '未対応';

todo のとき、または知らない値が来たときは、未対応 と表示します。


Step 6:priorityLabelを作る

次に、優先度を日本語に変える関数を作ります。

TaskCard の中に、次の関数を追加します。

String priorityLabel(String value) {
  switch (value) {
    case 'high':
      return '優先度:高';
    case 'low':
      return '優先度:低';
    case 'normal':
    default:
      return '優先度:中';
  }
}

変換ルールはこうです。

Firestoreの値画面表示
low優先度:低
normal優先度:中
high優先度:高

Step 7:priorityLabelの意味

この部分を見ます。

case 'high':
  return '優先度:高';

priorityhigh のとき、画面には 優先度:高 と表示します。

次は低です。

case 'low':
  return '優先度:低';

prioritylow のとき、画面には 優先度:低 と表示します。

最後は中です。

case 'normal':
default:
  return '優先度:中';

normal のとき、または知らない値が来たときは、優先度:中 と表示します。


Step 8:TaskCardの中で使う

TaskCard の表示部分で、次のように使います。

Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    _Label(text: statusLabel(status)),
    _Label(text: priorityLabel(priority)),
  ],
),

ここで、英語データを日本語ラベルに変えています。

status
↓
statusLabel(status)
↓
未対応 / 進行中 / 完了

priority
↓
priorityLabel(priority)
↓
優先度:低 / 優先度:中 / 優先度:高

Step 9:TaskCardの完成形を確認する

TaskCard は、次の形になっていればOKです。

class TaskCard extends StatelessWidget {
  const TaskCard({
    super.key,
    required this.title,
    required this.description,
    required this.status,
    required this.priority,
    required this.assigneeEmail,
    required this.onTap,
  });

  final String title;
  final String description;
  final String status;
  final String priority;
  final String assigneeEmail;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.centerLeft,
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          onTap: onTap,
          borderRadius: BorderRadius.circular(18),
          child: Container(
            width: double.infinity,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(4),
                topRight: Radius.circular(18),
                bottomLeft: Radius.circular(18),
                bottomRight: Radius.circular(18),
              ),
              border: Border.all(color: AppColors.border),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withValues(alpha: 0.04),
                  blurRadius: 10,
                  offset: const Offset(0, 4),
                ),
              ],
            ),
            padding: const EdgeInsets.all(14),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Wrap(
                  spacing: 8,
                  runSpacing: 8,
                  children: [
                    _Label(text: statusLabel(status)),
                    _Label(text: priorityLabel(priority)),
                  ],
                ),
                const SizedBox(height: 10),
                Text(
                  title,
                  style: const TextStyle(
                    color: AppColors.text,
                    fontSize: 16,
                    fontWeight: FontWeight.w900,
                  ),
                ),
                if (description.isNotEmpty) ...[
                  const SizedBox(height: 6),
                  Text(
                    description,
                    style: const TextStyle(
                      color: AppColors.subText,
                      height: 1.5,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ],
                if (assigneeEmail.isNotEmpty) ...[
                  const SizedBox(height: 12),
                  Container(
                    decoration: BoxDecoration(
                      color: AppColors.bg,
                      borderRadius: BorderRadius.circular(999),
                    ),
                    padding: const EdgeInsets.symmetric(
                      horizontal: 10,
                      vertical: 6,
                    ),
                    child: Text(
                      '担当:$assigneeEmail',
                      style: const TextStyle(
                        color: AppColors.subText,
                        fontSize: 12,
                        fontWeight: FontWeight.w800,
                      ),
                    ),
                  ),
                ],
              ],
            ),
          ),
        ),
      ),
    );
  }

  String statusLabel(String value) {
    switch (value) {
      case 'doing':
        return '進行中';
      case 'done':
        return '完了';
      case 'todo':
      default:
        return '未対応';
    }
  }

  String priorityLabel(String value) {
    switch (value) {
      case 'high':
        return '優先度:高';
      case 'low':
        return '優先度:低';
      case 'normal':
      default:
        return '優先度:中';
    }
  }
}

withValues でエラーが出る場合は、次に変えてください。

color: Colors.black.withOpacity(0.04),

Step 10:_Labelを確認する

TaskCard では _Label を使っています。

まだない場合は、次を追加します。

class _Label extends StatelessWidget {
  const _Label({
    required this.text,
  });

  final String text;

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: AppColors.bg,
        borderRadius: BorderRadius.circular(999),
        border: Border.all(color: AppColors.border),
      ),
      padding: const EdgeInsets.symmetric(
        horizontal: 10,
        vertical: 4,
      ),
      child: Text(
        text,
        style: const TextStyle(
          color: AppColors.subText,
          fontSize: 12,
          fontWeight: FontWeight.w800,
        ),
      ),
    );
  }
}

_Label は、短い文字を小さなラベルとして表示する部品です。


Step 11:保存する

main.dart を保存します。

Macの場合:

command + S

Windowsの場合:

Ctrl + S

Step 12:実行する

ターミナルで実行します。

flutter run

すでに起動している場合は、ターミナルで r を押します。

r

うまく反映されない場合は、R でホットリスタートします。

R

Step 13:画面で確認する

アプリを開きます。

ログイン
↓
トーク一覧
↓
チームをタップ
↓
タスク一覧画面

タスクカードに次のようなラベルが表示されればOKです。

未対応 優先度:中

ステータスや優先度を変えると、表示も変わります。

進行中 優先度:高
完了 優先度:低

Step 14:Firestoreで値を変えて確認する

Firebase Consoleで、タスクの値を変更して確認できます。

確認場所はこちらです。

Firestore Database
↓
teams
↓
作成したteamId
↓
tasks
↓
確認したいtaskId

status を変えてみます。

todo → doing → done

画面表示はこう変わります。

未対応 → 進行中 → 完了

次に、priority を変えてみます。

low → normal → high

画面表示はこう変わります。

優先度:低 → 優先度:中 → 優先度:高

よくあるエラーと直し方

エラー原因直し方
statusLabel isn't defined関数がないTaskCard の中に追加
priorityLabel isn't defined関数がないTaskCard の中に追加
_Label isn't defined_Label がない_Label を追加
ずっと未対応になるstatus の値が違うtodo / doing / done にする
ずっと優先度:中になるpriority の値が違うlow / normal / high にする
withValues でエラーFlutterのバージョン差withOpacity(0.04) に変える
表示が変わらない保存していないcommand + S

英語データで保存する理由

Firestoreには、日本語ではなく英語データで保存します。

todo
doing
done
low
normal
high

理由は、コードで扱いやすいからです。

たとえば、ステータス変更処理を書くときに、英語の短い値の方が安全です。

if (status == 'done') {
  // 完了の処理
}

画面に出すときだけ、日本語に変えます。

保存は英語
表示は日本語

この考え方が大事です。


知らない値が来たとき

たとえば、Firestoreに間違えて次のように保存したとします。

status: started
priority: very_high

今回の関数では、知らない値が来た場合は安全な表示にします。

status → 未対応
priority → 優先度:中

そのために、default を入れています。

default:
  return '未対応';
default:
  return '優先度:中';

最短作業まとめ

読むのが大変な人は、ここだけ見てください。

1. statusLabelを作る

String statusLabel(String value) {
  switch (value) {
    case 'doing':
      return '進行中';
    case 'done':
      return '完了';
    case 'todo':
    default:
      return '未対応';
  }
}

2. priorityLabelを作る

String priorityLabel(String value) {
  switch (value) {
    case 'high':
      return '優先度:高';
    case 'low':
      return '優先度:低';
    case 'normal':
    default:
      return '優先度:中';
  }
}

3. 表示に使う

Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    _Label(text: statusLabel(status)),
    _Label(text: priorityLabel(priority)),
  ],
)

4. 保存して実行

flutter run

チェックリスト

□ main.dartを開いた
□ TaskCardを探した
□ statusLabel()を作った
□ todoを未対応にした
□ doingを進行中にした
□ doneを完了にした
□ priorityLabel()を作った
□ lowを優先度:低にした
□ normalを優先度:中にした
□ highを優先度:高にした
□ _Labelで表示した
□ 保存した
□ flutter runで確認した

ミニ確認問題

Q1. todo は画面では何と表示しますか?

回答

未対応 と表示します。


Q2. doing は画面では何と表示しますか?

回答

進行中 と表示します。


Q3. done は画面では何と表示しますか?

回答

完了 と表示します。


Q4. normal は画面では何と表示しますか?

回答

優先度:中 と表示します。


Q5. なぜFirestoreには英語データで保存しますか?

回答

コードで扱いやすくするためです。

画面に出すときだけ、日本語に変えます。


このページのまとめ

  • Firestoreには英語の短い値で保存する。
  • 画面には日本語で表示する。
  • statusLabel()todo / doing / done を日本語に変える。
  • priorityLabel()low / normal / high を日本語に変える。
  • 知らない値が来たときは default で安全な表示にする。
  • TaskCard の中で _Label(text: statusLabel(status)) のように使う。
  • このページではnpmや環境変数は不要。

次のページでやること

次のページでは、メンバー一覧画面を作ります。

teams/{teamId}/members を取得して、チームに参加しているユーザーを表示します。

教材トップへ戻る