【TeamCard】チームをLINEのトーク一覧風に表示する
このページでやること
このページでは、チーム一覧の1件分を表示する TeamCard を作ります。
TeamCard とは、チーム名をLINEのトーク一覧のように表示するための部品です。
前のページでは、Firestoreから参加中チームを取得しました。
今回は、その取得したチームを見やすく表示します。
参加中チームを取得
↓
1件ずつTeamCardで表示
↓
LINEのトーク一覧風に見える
今日のゴール
チーム一覧が、次のように表示されるようにします。
〇 開発チーム >
〇 営業チーム >
〇 デザイン確認チーム >
見た目のイメージは、LINEのトーク一覧です。
左:丸いアイコン
中央:チーム名
右:矢印
このページで出てくる単語
| 単語 | 一言説明 |
|---|---|
TeamCard | チーム1件分を表示する部品 |
CircleAvatar | 丸いアイコンを作るWidget |
Row | 横並びにするWidget |
Expanded | 残りの横幅を使うWidget |
onTap | タップしたときの処理 |
VoidCallback | 引数なし・戻り値なしの処理 |
Icon | アイコンを表示するWidget |
Widget とは、Flutterの画面部品のことです。
npmや環境変数はこのページで必要?
このページでは、npmは使いません。
環境変数も設定しません。
このページでやることは、main.dart に TeamCard を追加して、チーム一覧で使うことです。
main.dartを開く
↓
TeamCardを作る
↓
ListViewの中でTeamCardを使う
↓
保存する
↓
flutter runで確認する
Step 1:main.dartを開く
次のファイルを開きます。
lib/main.dart
VS Codeを使っている場合は、ターミナルで次を実行してもOKです。
code lib/main.dart
Step 2:TeamCardを追加する
AppCard や ErrorBox の近くに、次のコードを追加します。
class TeamCard extends StatelessWidget {
const TeamCard({
super.key,
required this.name,
required this.onTap,
});
final String name;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final initial = name.isNotEmpty ? name.characters.first : '?';
return AppCard(
onTap: onTap,
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColors.lineGreen,
child: Text(
initial,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.text,
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
),
const Icon(
Icons.chevron_right,
color: AppColors.subText,
),
],
),
);
}
}
これで、チーム1件分の見た目をまとめられます。
Step 3:TeamCardの中身を確認する
TeamCard の中身は、次の3つです。
左:CircleAvatar
中央:Text
右:Icon
コードでは、この部分です。
Row(
children: [
CircleAvatar(...),
SizedBox(width: 12),
Expanded(child: Text(...)),
Icon(Icons.chevron_right),
],
)
Row は、部品を横に並べるWidgetです。
Step 4:丸いアイコンを作る
この部分です。
CircleAvatar(
backgroundColor: AppColors.lineGreen,
child: Text(
initial,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
),
),
),
CircleAvatar は、丸いアイコンを作るWidgetです。
今回は、チーム名の1文字目を丸の中に表示します。
たとえば、
開発チーム → 開
営業チーム → 営
という表示になります。
Step 5:チーム名を表示する
この部分です。
Expanded(
child: Text(
name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.text,
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
),
Expanded は、残りの横幅を使うためのWidgetです。
maxLines: 1 は、1行だけ表示する設定です。
overflow: TextOverflow.ellipsis は、長い文字を ... で省略する設定です。
たとえば、
とても長いチーム名ですこれは...
のように表示されます。
Step 6:右側に矢印を出す
この部分です。
const Icon(
Icons.chevron_right,
color: AppColors.subText,
),
Icons.chevron_right は、右向き矢印のアイコンです。
これがあると、ユーザーに「タップできる」と伝わりやすくなります。
Step 7:ListViewの中でTeamCardを使う
前のページでは、チーム一覧の中で AppCard を直接使っていました。
この部分を探してください。
return AppCard(
onTap: () {
// 次のページでタスク一覧画面へ移動します
},
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColors.lineGreen,
child: Text(
name.isNotEmpty ? name.characters.first : '?',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
name,
style: const TextStyle(
color: AppColors.text,
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
),
const Icon(
Icons.chevron_right,
color: AppColors.subText,
),
],
),
);
これを、次の短いコードに置き換えます。
return TeamCard(
name: name,
onTap: () {
// 次のページでタスク一覧画面へ移動します
},
);
これで、一覧表示のコードが短くなります。
Step 8:ListViewの完成形
ListView.separated の中は、次の形になります。
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: teams.length,
separatorBuilder: (_, __) => const SizedBox(height: 10),
itemBuilder: (context, index) {
final doc = teams[index];
final data = doc.data();
final name = (data['name'] ?? '無題のチーム').toString();
return TeamCard(
name: name,
onTap: () {
// 次のページでタスク一覧画面へ移動します
},
);
},
);
ListView.separated は、一覧の間に余白を入れられるListViewです。
separatorBuilder が、チームとチームの間の余白を作っています。
Step 9:保存する
main.dart を保存します。
Macの場合:
command + S
Windowsの場合:
Ctrl + S
Step 10:実行する
ターミナルで実行します。
flutter run
すでに起動している場合は、ターミナルで r を押します。
r
うまく反映されない場合は、R でホットリスタートします。
R
Step 11:画面を確認する
ログイン後、トーク一覧画面を見ます。
チームがある場合、次のように表示されればOKです。
丸アイコン チーム名 >
たとえば、
開 開発チーム >
営 営業チーム >
のような見た目になれば成功です。
Step 12:チームがない場合
まだチームがない場合は、先に右下の + ボタンから作成します。
右下の+
↓
チーム名を入力
↓
作成する
↓
一覧に表示される
例:
開発チーム
営業チーム
作成すると、TeamCard として一覧に表示されます。
1か所だけ変更してみる
丸アイコンの色を少し変えてみます。
この部分を探します。
backgroundColor: AppColors.lineGreen,
次のように変えてみます。
backgroundColor: AppColors.lineGreenDark,
保存して、ホットリロードします。
r
丸アイコンの緑が少し濃くなれば成功です。
確認できたら、元に戻してOKです。
backgroundColor: AppColors.lineGreen,
よくあるエラーと直し方
| エラー | 原因 | 直し方 |
|---|---|---|
TeamCard isn't defined | TeamCardを追加していない | class TeamCard を追加する |
VoidCallback isn't defined | Materialのimportがない | import 'package:flutter/material.dart'; を確認 |
characters が見つからない | 文字処理でエラー | 下の修正版を使う |
| 画面が変わらない | 保存していない | command + S |
| チームが表示されない | Firestore取得ができていない | 前ページの where arrayContains を確認 |
| タップしても何も起きない | まだ画面遷移を書いていない | 次のページで対応 |
characters** でエラーが出る場合**
この行でエラーが出る場合があります。
final initial = name.isNotEmpty ? name.characters.first : '?';
その場合は、次のように変更してください。
final initial = name.isNotEmpty ? name.substring(0, 1) : '?';
ただし、日本語や絵文字を安全に扱うなら、characters.first の方が向いています。
もし characters が使えない場合は、main.dart の上に次を追加します。
import 'package:flutter/services.dart';
ただし、通常のFlutter環境では name.characters.first が使えることが多いです。
タップしても何も起きない理由
今の段階では、onTap の中にまだ画面移動を書いていません。
onTap: () {
// 次のページでタスク一覧画面へ移動します
},
このページでは、表示だけできればOKです。
次のページで、チームをタップしたときに TaskListPage へ移動します。
最短作業まとめ
読むのが大変な人は、ここだけ見てください。
1. TeamCardを追加
class TeamCard extends StatelessWidget {
const TeamCard({
super.key,
required this.name,
required this.onTap,
});
final String name;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final initial = name.isNotEmpty ? name.characters.first : '?';
return AppCard(
onTap: onTap,
child: Row(
children: [
CircleAvatar(
backgroundColor: AppColors.lineGreen,
child: Text(
initial,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
),
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.text,
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
),
const Icon(
Icons.chevron_right,
color: AppColors.subText,
),
],
),
);
}
}
2. ListViewの中で使う
return TeamCard(
name: name,
onTap: () {
// 次のページでタスク一覧画面へ移動します
},
);
3. 保存して実行
flutter run
チェックリスト
□ main.dartを開いた
□ TeamCardを追加した
□ nameを受け取れるようにした
□ onTapを受け取れるようにした
□ CircleAvatarを使った
□ チーム名の1文字目を表示した
□ チーム名をTextで表示した
□ 右側に矢印アイコンを表示した
□ ListViewの中でTeamCardを使った
□ 保存した
□ flutter runで確認した
□ チームがLINEのトーク一覧風に表示された
ミニ確認問題
Q1. TeamCardは何のために作りますか?
回答
チーム1件分を、LINEのトーク一覧のような見た目で表示するためです。
Q2. CircleAvatarは何を作るWidgetですか?
回答
丸いアイコンを作るWidgetです。
今回は、チーム名の1文字目を丸の中に表示します。
Q3. overflow: TextOverflow.ellipsis は何をしますか?
回答
文字が長すぎるときに、末尾を ... で省略します。
Q4. このページでnpmや環境変数は必要ですか?
回答
必要ありません。
このページでは、チーム一覧の見た目を整える TeamCard を作るだけです。
このページのまとめ
TeamCardは、チーム1件分を表示する共通UI。- LINEのトーク一覧風に、左に丸アイコン、中央にチーム名、右に矢印を置く。
- チーム名の1文字目を
CircleAvatarに表示する。 - 長いチーム名は
...で省略する。 ListViewの中でTeamCardを使うと、コードが短くなる。- このページではnpmや環境変数は不要。
- 今回は表示だけでOK。
- タップ時の画面移動は次のページで作る。
次のページでやること
次のページでは、チームカードをタップして、タスク一覧画面へ移動します。
teamId と teamName を渡して、選んだチームのタスクだけを表示する準備をします。
