CONTENT
ここから
前の節では、API取得失敗時のエラー表示を作りました。
今回は、アプリ全体の見た目を少し整えて、ポケモン図鑑風の検索アプリに近づけます。
本物のポケモン図鑑を完全再現するのではなく、教材として扱いやすいように、赤・白・カード・丸い画像エリアを使って雰囲気を作ります。
出典なし。
この節で作ること
| 作業 | 内容 |
|---|---|
| 背景色を整える | 薄い赤系の背景にする |
| AppBarを赤くする | 図鑑らしい印象にする |
| 検索エリアをカード化する | 入力欄とボタンを見やすくする |
| 結果カードを調整する | 画像・番号・名前を中央に配置する |
忙しい方はここだけ見て
デザイン調整の中心は、次の3つです。
backgroundColor: const Color(0xFFFFF3F3),
appBar: AppBar(
title: const Text('ポケモン図鑑'),
backgroundColor: const Color(0xFFE53935),
foregroundColor: Colors.white,
),
Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
)
色・角丸・余白を整えるだけで、アプリの印象はかなり変わります。
手順1:背景色を変更する
Scaffold に backgroundColor を追加します。
Scaffold(
backgroundColor: const Color(0xFFFFF3F3),
appBar: AppBar(
title: const Text('ポケモン図鑑'),
),
)
薄い赤系の背景にすると、ポケモン図鑑らしい雰囲気が出ます。
手順2:AppBarを赤くする
AppBar を次のように変更します。
appBar: AppBar(
title: const Text('ポケモン図鑑'),
centerTitle: true,
backgroundColor: const Color(0xFFE53935),
foregroundColor: Colors.white,
),
backgroundColor は背景色です。foregroundColor は文字やアイコンの色です。
手順3:検索エリアをカードにする
入力欄と検索ボタンを、白いカードの中に入れます。
Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: <Widget>[
TextField(
controller: _pokemonIdController,
keyboardType: TextInputType.number,
enabled: !_isLoading,
decoration: const InputDecoration(
labelText: 'ポケモン番号',
hintText: '例: 25',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _searchPokemon,
child: Text(_isLoading ? '検索中...' : '検索する'),
),
),
],
),
),
)
入力欄とボタンをカードにまとめると、「検索エリア」として分かりやすくなります。
手順4:検索ボタンを赤くする
ElevatedButton に style を追加します。
ElevatedButton(
onPressed: _isLoading ? null : _searchPokemon,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFE53935),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
child: Text(_isLoading ? '検索中...' : '検索する'),
)
ボタンも赤にすると、アプリ全体の印象がまとまります。
手順5:結果カードを図鑑風にする
検索結果のカードを少し整えます。
Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: <Widget>[
Text(
'No. $_pokemonIdText',
style: const TextStyle(
fontSize: 16,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
Container(
width: 180,
height: 180,
decoration: BoxDecoration(
color: Color(0xFFF5F5F5),
shape: BoxShape.circle,
),
child: Image.network(
_pokemonImageUrl!,
fit: BoxFit.contain,
),
),
const SizedBox(height: 20),
Text(
_pokemonName,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
],
),
),
)
画像の後ろに丸い背景を入れると、キャラクターが見やすくなります。
完成コード
build() の中を中心に、次のように整えます。
/**
* ポケモン検索画面を構築する関数。
*
* 入力: BuildContext
* 出力: Scaffold
*/
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFFFF3F3),
appBar: AppBar(
title: const Text('ポケモン図鑑'),
centerTitle: true,
backgroundColor: const Color(0xFFE53935),
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
children: <Widget>[
Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: <Widget>[
TextField(
controller: _pokemonIdController,
keyboardType: TextInputType.number,
enabled: !_isLoading,
decoration: const InputDecoration(
labelText: 'ポケモン番号',
hintText: '例: 25',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _searchPokemon,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFE53935),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
child: Text(_isLoading ? '検索中...' : '検索する'),
),
),
],
),
),
),
const SizedBox(height: 32),
if (_isLoading)
const CircularProgressIndicator()
else if (_errorMessage != null)
Text(
_errorMessage!,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red,
),
)
else if (_pokemonImageUrl != null)
Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: <Widget>[
Text(
'No. $_pokemonIdText',
style: const TextStyle(
fontSize: 16,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
Container(
width: 180,
height: 180,
decoration: const BoxDecoration(
color: Color(0xFFF5F5F5),
shape: BoxShape.circle,
),
child: Image.network(
_pokemonImageUrl!,
fit: BoxFit.contain,
),
),
const SizedBox(height: 20),
Text(
_pokemonName,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
],
),
),
)
else
Text(
_pokemonName,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
動作確認
アプリを起動します。
flutter run
25 と入力して検索します。
pikachu
赤いヘッダー、白い検索カード、丸い画像エリア、結果カードが表示されれば成功です。
よくあるエラー
| エラー | 原因 | 対応 |
|---|---|---|
| 画面が詰まる | 余白が少ない | Padding や SizedBox を増やす |
| 画像が大きすぎる | サイズ指定がない | Container の幅と高さを指定する |
| ボタンの色が変わらない | style がない | ElevatedButton.styleFrom() を使う |
| カードの角が丸くならない | shape がない | RoundedRectangleBorder を指定する |
まとめ
この節では、Flutterアプリをポケモン図鑑風に整えました。
大事なポイントは3つです。
| ポイント | 内容 |
|---|---|
| 色 | 赤・白・薄赤で雰囲気を作る |
| 余白 | Padding と SizedBox で見やすくする |
| カードUI | 検索エリアと結果を分ける |
機能は同じでも、見た目を整えるだけでアプリの完成度は大きく変わります。
次は、ここまで作った機能を振り返りながら、アプリとして仕上げていきます。