Flutter UI Design Guidelines
Purpose
このスキルは、FlutterアプリのUIを「ありきたりなデフォルト」から脱却させ、プロフェッショナルで印象的なデザインを実現するためのガイドラインを提供します。
Typography(タイポグラフィ)
避けるべきパターン
- デフォルトの
Robotoのみの使用 - 単調なフォントウェイト(Regular/Boldのみ)
- 均一なテキストサイズ
推奨アプローチ
dart1// Google Fontsでモダンなフォントを使用 2import 'package:google_fonts/google_fonts.dart'; 3 4// タイトル用: 個性的なディスプレイフォント 5GoogleFonts.poppins(fontWeight: FontWeight.w700) 6GoogleFonts.inter(fontWeight: FontWeight.w800) 7GoogleFonts.plusJakartaSans() 8 9// 本文用: 読みやすいサンセリフ 10GoogleFonts.inter() 11GoogleFonts.dmSans() 12 13// コントラストを意識したサイズ階層 14headlineLarge: 32sp, weight: 800 15headlineMedium: 24sp, weight: 700 16titleLarge: 20sp, weight: 600 17bodyLarge: 16sp, weight: 400 18labelSmall: 12sp, weight: 500
フォントウェイトの活用
- 極端なコントラスト:
w300とw800を組み合わせる - 見出しは太く(w600-w800)、本文は通常(w400)
Color & Theme(カラー・テーマ)
避けるべきパターン
- Material Design のデフォルト青/紫
- 控えめで均等なカラーパレット
- 灰色ばかりの無難なUI
推奨アプローチ
dart1// ダークテーマ: 深みのある背景 + 鮮やかなアクセント 2ColorScheme.dark( 3 surface: Color(0xFF0F0F14), // 深いダークグレー 4 surfaceContainerHighest: Color(0xFF1A1A23), 5 primary: Color(0xFF6366F1), // 鮮やかなインディゴ 6 secondary: Color(0xFF22D3EE), // シアンアクセント 7 tertiary: Color(0xFFF472B6), // ピンクアクセント 8) 9 10// ライトテーマ: クリーンな白 + ビビッドなアクセント 11ColorScheme.light( 12 surface: Color(0xFFFAFAFC), 13 surfaceContainerHighest: Color(0xFFF1F5F9), 14 primary: Color(0xFF4F46E5), // インディゴ 15 secondary: Color(0xFF0EA5E9), // スカイブルー 16 tertiary: Color(0xFFEC4899), // ピンク 17)
カラー活用のポイント
- Dominant Color: 1つのプライマリカラーを大胆に使用
- Sharp Accents: セカンダリカラーはアクセントとして控えめに
- Semantic Colors: 成功=緑、エラー=赤、警告=黄は直感的に
Elevation & Depth(立体感)
避けるべきパターン
- フラットすぎるデザイン
- 均一なelevation
- 影の乱用
推奨アプローチ
dart1// カードに微妙な立体感 2Card( 3 elevation: 0, 4 shape: RoundedRectangleBorder( 5 borderRadius: BorderRadius.circular(16), 6 ), 7 color: theme.colorScheme.surfaceContainerHighest, 8 child: ... 9) 10 11// ソフトシャドウ(コントラスト控えめ) 12BoxDecoration( 13 borderRadius: BorderRadius.circular(16), 14 boxShadow: [ 15 BoxShadow( 16 color: Colors.black.withOpacity(0.04), 17 blurRadius: 10, 18 offset: Offset(0, 4), 19 ), 20 ], 21) 22 23// グラスモーフィズム効果 24ClipRRect( 25 borderRadius: BorderRadius.circular(16), 26 child: BackdropFilter( 27 filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), 28 child: Container( 29 color: Colors.white.withOpacity(0.1), 30 child: ... 31 ), 32 ), 33)
Motion & Animation(アニメーション)
避けるべきパターン
- アニメーションなしの硬いUI
- 過剰で散漫なアニメーション
- 一貫性のないタイミング
推奨アプローチ
dart1// ページ遷移: スムーズなフェード+スライド 2PageRouteBuilder( 3 transitionDuration: Duration(milliseconds: 300), 4 pageBuilder: (_, __, ___) => DestinationPage(), 5 transitionsBuilder: (_, animation, __, child) { 6 return FadeTransition( 7 opacity: animation, 8 child: SlideTransition( 9 position: Tween<Offset>( 10 begin: Offset(0, 0.05), 11 end: Offset.zero, 12 ).animate(CurvedAnimation( 13 parent: animation, 14 curve: Curves.easeOutCubic, 15 )), 16 child: child, 17 ), 18 ); 19 }, 20) 21 22// リスト項目: Staggered Animation 23AnimatedList + interval-based delays 24 25// タップフィードバック: 微細なスケール 26Transform.scale( 27 scale: isPressed ? 0.98 : 1.0, 28 child: AnimatedContainer( 29 duration: Duration(milliseconds: 100), 30 ... 31 ), 32)
タイミングの指針
- 短い操作(タップ): 100-150ms
- 画面遷移: 250-350ms
- 複雑なアニメーション: 400-600ms
- Curve:
easeOutCubic、easeInOutCubicを基本に
Layout & Spacing(レイアウト・余白)
避けるべきパターン
- 詰まりすぎたUI
- 不規則なパディング
- 要素間の余白不足
推奨アプローチ
dart1// 8px基準のスペーシングシステム 2const spacing = ( 3 xs: 4.0, 4 sm: 8.0, 5 md: 16.0, 6 lg: 24.0, 7 xl: 32.0, 8 xxl: 48.0, 9); 10 11// コンテンツエリアの余白 12Padding( 13 padding: EdgeInsets.symmetric(horizontal: 20, vertical: 16), 14 child: ... 15) 16 17// カード内の余白は外より大きく 18Card( 19 child: Padding( 20 padding: EdgeInsets.all(20), 21 child: ... 22 ), 23) 24 25// 要素間のギャップ 26SizedBox(height: 16) // 関連要素間 27SizedBox(height: 32) // セクション間
Components(コンポーネント)
ボタン
dart1// プライマリボタン: 角丸 + 十分なパディング 2FilledButton( 3 style: FilledButton.styleFrom( 4 padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), 5 shape: RoundedRectangleBorder( 6 borderRadius: BorderRadius.circular(12), 7 ), 8 ), 9 child: Text('Action'), 10) 11 12// アウトラインボタン 13OutlinedButton( 14 style: OutlinedButton.styleFrom( 15 side: BorderSide(color: theme.colorScheme.outline, width: 1.5), 16 shape: RoundedRectangleBorder( 17 borderRadius: BorderRadius.circular(12), 18 ), 19 ), 20)
入力フィールド
dart1TextField( 2 decoration: InputDecoration( 3 filled: true, 4 fillColor: theme.colorScheme.surfaceContainerHighest, 5 border: OutlineInputBorder( 6 borderRadius: BorderRadius.circular(12), 7 borderSide: BorderSide.none, 8 ), 9 focusedBorder: OutlineInputBorder( 10 borderRadius: BorderRadius.circular(12), 11 borderSide: BorderSide( 12 color: theme.colorScheme.primary, 13 width: 2, 14 ), 15 ), 16 contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), 17 ), 18)
FAB
dart1FloatingActionButton( 2 elevation: 2, 3 shape: RoundedRectangleBorder( 4 borderRadius: BorderRadius.circular(16), 5 ), 6 child: Icon(Icons.add), 7)
Background(背景)
推奨テクニック
dart1// グラデーション背景 2Container( 3 decoration: BoxDecoration( 4 gradient: LinearGradient( 5 begin: Alignment.topLeft, 6 end: Alignment.bottomRight, 7 colors: [ 8 theme.colorScheme.surface, 9 theme.colorScheme.surface.withOpacity(0.95), 10 ], 11 ), 12 ), 13) 14 15// サブトルなパターン(ドット、グリッド) 16CustomPaint( 17 painter: DotPatternPainter( 18 color: theme.colorScheme.outline.withOpacity(0.05), 19 spacing: 20, 20 ), 21)
Checklist
UIを実装する際のチェックリスト:
- デフォルトフォント以外を使用しているか
- カラーパレットにアクセントカラーがあるか
- 適切な余白・パディングが設定されているか
- インタラクションにフィードバック(アニメーション)があるか
- コンポーネントの角丸が統一されているか(12-16px推奨)
- テキストの階層(サイズ・ウェイト)が明確か