Primary About Development

Flutterのよく使うWidgetの命名(Suffix)をまとめてみる

2024-07-08

はじめに

Flutterアプリケーション開発において、適切なウィジェット命名は、コードの可読性、保守性、そして全体的な品質を大きく左右します。本記事では、効果的なウィジェットサフィックスの使用方法について、実践的な例を交えながら詳しく解説します。

なぜウィジェットサフィックスが重要か

ウィジェットサフィックスは以下の理由で重要です:

  1. 明確さ: ウィジェットの目的とタイプを即座に伝えます。
  2. 一貫性: プロジェクト全体で統一的な命名規則を維持します。
  3. 整理: 大規模なコードベースでのウィジェットの分類と検索を容易にします。
  4. コミュニケーション: チーム内で共通の語彙を確立し、コミュニケーションを円滑にします。

それでは、各カテゴリーと具体的なサフィックスについて、詳細に見ていきましょう。

1. 画面レベルのコンポーネント

このグループは、アプリケーションの主要な画面や大きなビューを表すコンポーネントを含みます。

Page

  • 説明: フルページを表し、主にWebコンテキストで使用されます。
  • 詳細: 複数のScreenViewを含む可能性があり、アプリケーションの最上位レベルのナビゲーション単位となることが多いです。
  • : HomePage, ProfilePage, SettingsPage
class HomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('ホーム')),
      body: Column(
        children: [
          WelcomeSection(),
          RecentActivityList(),
          QuickActionButtons(),
        ],
      ),
    );
  }
}

Screen

  • 説明: 通常、モバイルアプリの完全な画面に使用されます。
  • 詳細: 一つの機能や目的に特化した独立した画面を表します。
  • : LoginScreen, ProductDetailScreen, NotificationScreen
class LoginScreen extends StatefulWidget {
  
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            LoginForm(),
            ForgotPasswordButton(),
            SignUpPrompt(),
          ],
        ),
      ),
    );
  }
}

View

  • 説明: 画面の一部または再利用可能なビューコンポーネントを表します。
  • 詳細: Screenよりも小さい単位で、特定の情報や機能を表示するために使用されます。
  • : UserProfileView, ProductListView, OrderSummaryView
class UserProfileView extends StatelessWidget {
  final User user;

  UserProfileView({required this.user});

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        UserAvatar(user: user),
        UserInfoSection(user: user),
        UserStatsDisplay(user: user),
      ],
    );
  }
}

2. コンテナコンポーネント

このグループは、他のウィジェットを包含し、レイアウトや視覚的なグループ化を提供するコンポーネントを含みます。

Container

  • 説明: 他のウィジェットの汎用ラッパー。
  • 詳細: パディング、マージン、境界線などの基本的なスタイリングを適用するために使用されます。
  • : ContentContainer, ImageContainer, ButtonContainer
class ContentContainer extends StatelessWidget {
  final Widget child;

  ContentContainer({required this.child});

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16),
      margin: EdgeInsets.symmetric(vertical: 8),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.2),
            spreadRadius: 2,
            blurRadius: 4,
            offset: Offset(0, 2),
          ),
        ],
      ),
      child: child,
    );
  }
}

Wrapper

  • 説明: ラップされたウィジェットに機能やスタイリングを追加します。
  • 詳細: 主に機能的な目的や、複雑なスタイリングの適用に使用されます。
  • : AuthWrapper, ThemeWrapper, ErrorBoundaryWrapper
class AuthWrapper extends StatelessWidget {
  final Widget child;

  AuthWrapper({required this.child});

  
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          User? user = snapshot.data;
          if (user == null) {
            return LoginScreen();
          }
          return child;
        }
        return LoadingScreen();
      },
    );
  }
}

Box

  • 説明: 特定のスタイリングや制約を持つコンテナ。
  • 詳細: Containerよりも具体的な用途を持ち、特定の視覚的スタイルや寸法制約を適用します。
  • : InfoBox, AlertBox, ImageBox
class AlertBox extends StatelessWidget {
  final String message;
  final Color color;

  AlertBox({required this.message, this.color = Colors.red});

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(12),
      margin: EdgeInsets.symmetric(vertical: 8),
      decoration: BoxDecoration(
        color: color.withOpacity(0.1),
        border: Border.all(color: color),
        borderRadius: BorderRadius.circular(4),
      ),
      child: Row(
        children: [
          Icon(Icons.warning, color: color),
          SizedBox(width: 8),
          Expanded(child: Text(message, style: TextStyle(color: color))),
        ],
      ),
    );
  }
}

Card

  • 説明: グループ化された情報を表示するためのカードライクなコンテナ。
  • 詳細: 通常、影やラウンドコーナーを持ち、関連情報をビジュアル的にグループ化します。
  • : ProductCard, UserCard, EventCard
class ProductCard extends StatelessWidget {
  final Product product;

  ProductCard({required this.product});

  
  Widget build(BuildContext context) {
    return Card(
      elevation: 2,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Image.network(product.imageUrl),
          Padding(
            padding: EdgeInsets.all(8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(product.name, style: Theme.of(context).textTheme.headline6),
                SizedBox(height: 4),
                Text('\$${product.price}', style: TextStyle(fontWeight: FontWeight.bold)),
                SizedBox(height: 4),
                Text(product.description, maxLines: 2, overflow: TextOverflow.ellipsis),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

3. リスト要素

このグループは、リストやグリッド内で繰り返し使用される個別の項目を表すコンポーネントを含みます。

Tile

  • 説明: リストやグリッド内の区別された、多くの場合タップ可能なアイテム。
  • 詳細: 通常、アイコンやサムネイルと共にテキスト情報を表示します。
  • : ContactTile, SettingsTile, NotificationTile
class ContactTile extends StatelessWidget {
  final Contact contact;
  final VoidCallback onTap;

  ContactTile({required this.contact, required this.onTap});

  
  Widget build(BuildContext context) {
    return ListTile(
      leading: CircleAvatar(
        backgroundImage: NetworkImage(contact.avatarUrl),
      ),
      title: Text(contact.name),
      subtitle: Text(contact.email),
      trailing: Icon(Icons.chevron_right),
      onTap: onTap,
    );
  }
}

Item

  • 説明: 汎用的なリストやコレクションのアイテム。
  • 詳細: Tileよりも一般的で、様々なタイプのリスト項目に使用できます。
  • : TodoItem, ShoppingCartItem, CommentItem
class TodoItem extends StatelessWidget {
  final Todo todo;
  final ValueChanged<bool> onComplete;

  TodoItem({required this.todo, required this.onComplete});

  
  Widget build(BuildContext context) {
    return Row(
      children: [
        Checkbox(
          value: todo.isCompleted,
          onChanged: (value) => onComplete(value ?? false),
        ),
        Expanded(
          child: Text(
            todo.title,
            style: TextStyle(
              decoration: todo.isCompleted ? TextDecoration.lineThrough : null,
            ),
          ),
        ),
      ],
    );
  }
}

Cell

  • 説明: グリッドやテーブル内の個別のセル。
  • 詳細: 主にデータ表示に使用され、通常はタップ可能ではありません。
  • : CalendarCell, DataCell, GridCell
class CalendarCell extends StatelessWidget {
  final DateTime date;
  final bool isSelected;
  final VoidCallback onTap;

  CalendarCell({required this.date, this.isSelected = false, required this.onTap});

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        decoration: BoxDecoration(
          color: isSelected ? Theme.of(context).primaryColor : null,
          border: Border.all(color: Colors.grey[300]!),
        ),
        child: Center(
          child: Text(
            '${date.day}',
            style: TextStyle(
              color: isSelected ? Colors.white : null,
              fontWeight: isSelected ? FontWeight.bold : null,
            ),
          ),
        ),
      ),
    );
  }
}

4. レイアウトコンポーネント

このグループは、他のウィジェットを特定の方法で配置するためのコンポーネントを含みます。全体的なページ構造を定義するのに役立ちます。

Row

  • 説明: ウィジェットの水平配置。
  • 詳細: 子ウィジェットを左から右に並べます。水平方向のスペース配分を管理するのに使用されます。
  • : MenuRow, ButtonRow, IconRow
class MenuRow extends StatelessWidget {
  final List<MenuItem> items;

  MenuRow({required this.items});

  
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: items.map((item) => 
        TextButton(
          onPressed: item.onTap,
          child: Text(item.title),
        )
      ).toList(),
    );
  }
}

Column

  • 説明: ウィジェットの垂直配置。
  • 詳細: 子ウィジェットを上から下に並べます。垂直方向のスペース配分を管理するのに使用されます。
  • : ProfileColumn, SettingsColumn, StatsColumn
class ProfileColumn extends StatelessWidget {
  final User user;

  ProfileColumn({required this.user});

  
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        CircleAvatar(backgroundImage: NetworkImage(user.avatarUrl)),
        SizedBox(height: 8),
        Text(user.name, style: Theme.of(context).textTheme.headline6),
        SizedBox(height: 4),
        Text(user.email, style: Theme.of(context).textTheme.subtitle1),
        SizedBox(height: 8),
        Text(user.bio, style: Theme.of(context).textTheme.bodyText2),
      ],
    );
  }
}

Grid

  • 説明: ウィジェットのグリッドレイアウト。
  • 詳細: 子ウィジェットを行と列の格子状に配置します。写真ギャラリーやダッシュボードなどに適しています。
  • : PhotoGrid, CategoryGrid, DashboardGrid
class PhotoGrid extends StatelessWidget {
  final List<String> photoUrls;

  PhotoGrid({required this.photoUrls});

  
  Widget build(BuildContext context) {
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
        crossAxisSpacing: 4,
        mainAxisSpacing: 4,
      ),
      itemCount: photoUrls.length,
      itemBuilder: (context, index) {
        return Image.network(
          photoUrls[index],
          fit: BoxFit.cover,
        );
      },
    );
  }
}

List

  • 説明: ウィジェットの線形配置。
  • 詳細: 子ウィジェットを縦または横に一列に並べます。スクロール可能なリストを作成する際によく使用されます。
  • : NotificationList, CommentList, ProductList
class NotificationList extends StatelessWidget {
  final List<Notification> notifications;

  NotificationList({required this.notifications});

  
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: notifications.length,
      itemBuilder: (context, index) {
        final notification = notifications[index];
        return ListTile(
          leading: Icon(notification.icon),
          title: Text(notification.title),
          subtitle: Text(notification.message),
          trailing: Text(notification.timeAgo),
          onTap: () => _handleNotificationTap(notification),
        );
      },
    );
  }

  void _handleNotificationTap(Notification notification) {
    // Handle notification tap
  }
}

5. 構造的コンポーネント

このグループは、アプリケーションの構造を形成し、コンテンツを論理的に分割するためのコンポーネントを含みます。

Panel

  • 説明: 関連する情報や制御のグループ化。
  • 詳細: 特定の機能や情報セットを独立して表示・制御するために使用されます。
  • : ControlPanel, InfoPanel, SettingsPanel
class ControlPanel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.grey[200],
        borderRadius: BorderRadius.circular(8),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Control Panel', style: Theme.of(context).textTheme.headline6),
          SizedBox(height: 16),
          ToggleButtons(
            children: [Icon(Icons.format_bold), Icon(Icons.format_italic), Icon(Icons.format_underline)],
            isSelected: [true, false, false],
            onPressed: (int index) {
              // Handle toggle
            },
          ),
          SizedBox(height: 16),
          Slider(
            value: 0.5,
            onChanged: (double value) {
              // Handle slider change
            },
          ),
        ],
      ),
    );
  }
}

Section

  • 説明: 画面やコンポーネント内の論理的な区分。
  • 詳細: 大きなコンテンツ領域を意味のある部分に分割します。
  • : ProfileSection, DetailsSection, SummarySection
class ProfileSection extends StatelessWidget {
  final User user;

  ProfileSection({required this.user});

  
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('Profile', style: Theme.of(context).textTheme.headline6),
        SizedBox(height: 8),
        ListTile(
          leading: Icon(Icons.person),
          title: Text(user.name),
          subtitle: Text('Name'),
        ),
        ListTile(
          leading: Icon(Icons.email),
          title: Text(user.email),
          subtitle: Text('Email'),
        ),
        ListTile(
          leading: Icon(Icons.phone),
          title: Text(user.phone),
          subtitle: Text('Phone'),
        ),
      ],
    );
  }
}

Block

  • 説明: 独立した機能単位。
  • 詳細: 特定の機能や情報を自己完結的に提供します。
  • : AdBlock, WeatherBlock, StatisticsBlock
class WeatherBlock extends StatelessWidget {
  final WeatherData weather;

  WeatherBlock({required this.weather});

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.blue[100],
        borderRadius: BorderRadius.circular(8),
      ),
      child: Column(
        children: [
          Icon(Icons.wb_sunny, size: 48, color: Colors.orange),
          SizedBox(height: 8),
          Text('${weather.temperature}°C', style: Theme.of(context).textTheme.headline4),
          Text(weather.condition, style: Theme.of(context).textTheme.subtitle1),
          SizedBox(height: 8),
          Text('Humidity: ${weather.humidity}%'),
          Text('Wind: ${weather.windSpeed} km/h'),
        ],
      ),
    );
  }
}

Fragment

  • 説明: 画面の再利用可能な部分。
  • 詳細: 複数の画面で使用される共通の UI 要素を表します。
  • : HeaderFragment, FooterFragment, SidebarFragment
class HeaderFragment extends StatelessWidget {
  final String title;
  final VoidCallback? onMenuPressed;

  HeaderFragment({required this.title, this.onMenuPressed});

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      color: Theme.of(context).primaryColor,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            title,
            style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
          ),
          if (onMenuPressed != null)
            IconButton(
              icon: Icon(Icons.menu, color: Colors.white),
              onPressed: onMenuPressed,
            ),
        ],
      ),
    );
  }
}

6. 再利用可能なUI要素

このグループは、アプリケーション全体で再利用可能な小さなUI要素を含みます。

Component

  • 説明: より大きな、自己完結型のUI要素。
  • 詳細: 複数の基本的なウィジェットを組み合わせて作られた、独立して機能する UI 要素です。
  • : RatingComponent, SearchComponent, PaginationComponent
class RatingComponent extends StatelessWidget {
  final double rating;
  final int maxRating;
  final double size;

  RatingComponent({
    required this.rating,
    this.maxRating = 5,
    this.size = 24,
  });

  
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: List.generate(maxRating, (index) {
        return Icon(
          index < rating.floor() ? Icons.star : Icons.star_border,
          color: Colors.amber,
          size: size,
        );
      }),
    );
  }
}

Element

  • 説明: 基本的なUI構成要素。
  • 詳細: アプリケーション全体で使用される最小単位の UI 要素です。
  • : IconElement, AvatarElement, BadgeElement
class BadgeElement extends StatelessWidget {
  final String text;
  final Color color;

  BadgeElement({required this.text, this.color = Colors.red});

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(12),
      ),
      child: Text(
        text,
        style: TextStyle(color: Colors.white, fontSize: 12),
      ),
    );
  }
}

7. 入力コンポーネント

このグループは、ユーザーからの入力を受け付けるためのコンポーネントを含みます。

Field

  • 説明: 単一のデータ入力フィールド。
  • 詳細: テキスト、数値、日付など、特定のタイプのデータ入力に特化したフィールドです。
  • : EmailField, PasswordField, DateField
class EmailField extends StatelessWidget {
  final TextEditingController controller;
  final String? Function(String?)? validator;

  EmailField({required this.controller, this.validator});

  
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      keyboardType: TextInputType.emailAddress,
      decoration: InputDecoration(
        labelText: 'Email',
        prefixIcon: Icon(Icons.email),
        border: OutlineInputBorder(),
      ),
      validator: validator ?? (value) {
        if (value == null || value.isEmpty) {
          return 'Please enter your email';
        }
        if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
          return 'Please enter a valid email address';
        }
        return null;
      },
    );
  }
}

Input

  • 説明: 一般的な入力要素。
  • 詳細: テキスト以外の入力(色選択、スライダーなど)も含む、より広範な入力タイプを表します。
  • : ColorInput, SliderInput, ToggleInput
class SliderInput extends StatefulWidget {
  final double initialValue;
  final double min;
  final double max;
  final ValueChanged<double> onChanged;

  SliderInput({
    required this.initialValue,
    required this.min,
    required this.max,
    required this.onChanged,
  });

  
  _SliderInputState createState() => _SliderInputState();
}

class _SliderInputState extends State<SliderInput> {
  late double _value;

  
  void initState() {
    super.initState();
    _value = widget.initialValue;
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Slider(
          value: _value,
          min: widget.min,
          max: widget.max,
          onChanged: (newValue) {
            setState(() {
              _value = newValue;
            });
            widget.onChanged(newValue);
          },
        ),
        Text('Value: ${_value.toStringAsFixed(2)}'),
      ],
    );
  }
}

Form

  • 説明: 入力フィールドのグループ。
  • 詳細: 複数の関連する入力フィールドをまとめ、全体としてのバリデーションや送信処理を管理します。
  • : LoginForm, RegistrationForm, ContactForm
class LoginForm extends StatefulWidget {
  
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          EmailField(controller: _emailController),
          SizedBox(height: 16),
          PasswordField(controller: _passwordController),
          SizedBox(height: 24),
          ElevatedButton(
            onPressed: _submitForm,
            child: Text('Login'),
          ),
        ],
      ),
    );
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      // Perform login logic
      print('Login with: ${_emailController.text}');
    }
  }

  
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }
}

8. ボタンコンポーネント

このグループは、ユーザーのアクションをトリガーするためのコンポーネントを含みます。

Button

  • 説明: アクション用のタップ可能なUI要素。
  • 詳細: ユーザーが押すことで特定のアクションを実行するUI要素です。
  • : SubmitButton, CancelButton, IconButton
class SubmitButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;
  final bool isLoading;

  SubmitButton({
    required this.text,
    required this.onPressed,
    this.isLoading = false,
  });

  
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: isLoading ? null : onPressed,
      child: isLoading
          ? SizedBox(
              width: 20,
              height: 20,
              child: CircularProgressIndicator(
                valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
              ),
            )
          : Text(text),
      style: ElevatedButton.styleFrom(
        padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
      ),
    );
  }
}

Action

  • 説明: ユーザーアクションを表す(ボタンに限定されない)。
  • 詳細: タップ、スワイプ、長押しなど、ボタン以外のジェスチャーによって引き起こされるアクションも含みます。
  • : SwipeAction, LongPressAction, DoubleTapAction
class SwipeAction extends StatelessWidget {
  final Widget child;
  final VoidCallback onSwipe;

  SwipeAction({required this.child, required this.onSwipe});

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onHorizontalDragEnd: (details) {
        if (details.primaryVelocity! < 0) {
          onSwipe();
        }
      },
      child: child,
    );
  }
}

9. 表示コンポーネント

このグループは、情報を視覚的に表示するためのコンポーネントを含みます。

Display

  • 説明: データの視覚的表現。
  • 詳細: グラフ、チャート、ダイアグラムなど、複雑なデータを視覚的に表現するコンポーネントです。
  • : ChartDisplay, GraphDisplay, StatisticsDisplay
class ChartDisplay extends StatelessWidget {
  final List<double> data;

  ChartDisplay({required this.data});

  
  Widget build(BuildContext context) {
    return Container(
      height: 200,
      padding: EdgeInsets.all(16),
      child: CustomPaint(
        painter: ChartPainter(data),
        size: Size.infinite,
      ),
    );
  }
}

class ChartPainter extends CustomPainter {
  final List<double> data;

  ChartPainter(this.data);

  
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;

    final path = Path();
    final width = size.width / (data.length - 1);
    final maxData = data.reduce(math.max);

    for (int i = 0; i < data.length; i++) {
      final x = i * width;
      final y = size.height - (data[i] / maxData * size.height);

      if (i == 0) {
        path.moveTo(x, y);
      } else {
        path.lineTo(x, y);
      }
    }

    canvas.drawPath(path, paint);
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

Text

  • 説明: テキスト表示コンポーネント。
  • 詳細: 単純なテキスト表示から、スタイル付きテキスト、複数行テキストまで、様々なテキスト表示に使用されます。
  • : HeadlineText, DescriptionText, ErrorText
class HeadlineText extends StatelessWidget {
  final String text;
  final TextAlign textAlign;

  HeadlineText({required this.text, this.textAlign = TextAlign.left});

  
  Widget build(BuildContext context) {
    return Text(
      text,
      style: Theme.of(context).textTheme.headline4,
      textAlign: textAlign,
    );
  }
}

Label

  • 説明: 他の要素の短いテキスト記述子。
  • 詳細: フォームフィールドのラベルや、短い説明テキストなど、他のUI要素を説明するための短いテキストに使用されます。
  • : FieldLabel, StatusLabel, PriceLabel
class StatusLabel extends StatelessWidget {
  final String status;

  StatusLabel({required this.status});

  
  Widget build(BuildContext context) {
    Color color;
    IconData icon;

    switch (status.toLowerCase()) {
      case 'active':
        color = Colors.green;
        icon = Icons.check_circle;
        break;
      case 'pending':
        color = Colors.orange;
        icon = Icons.access_time;
        break;
      case 'inactive':
        color = Colors.red;
        icon = Icons.cancel;
        break;
      default:
        color = Colors.grey;
        icon = Icons.help;
    }

    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon, color: color, size: 16),
        SizedBox(width: 4),
        Text(
          status,
          style: TextStyle(color: color, fontWeight: FontWeight.bold),
        ),
      ],
    );
  }
}

10. ナビゲーションコンポーネント

このグループは、アプリケーション内のナビゲーションを管理するためのコンポーネントを含みます。

Bar

  • 説明: 固定位置のナビゲーション要素。
  • 詳細: アプリの上部(AppBar)や下部(BottomNavigationBar)に固定されるナビゲーション要素です。
  • : TopBar, BottomBar, SideBar
class BottomBar extends StatelessWidget {
  final int currentIndex;
  final ValueChanged<int> onTap;

  BottomBar({required this.currentIndex, required this.onTap});

  
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      currentIndex: currentIndex,
      onTap: onTap,
      items: [
        BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
        BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
        BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
      ],
    );
  }
}

Menu

  • 説明: 選択可能なナビゲーション項目のリスト。
  • 詳細: ドロップダウンメニュー、サイドメニュー、コンテキストメニューなど、複数のナビゲーションオプションを提供するコンポーネントです。
  • : DropdownMenu, SideMenu, ContextMenu
class SideMenu extends StatelessWidget {
  final List<MenuItem> items;
  final ValueChanged<MenuItem> onItemSelected;

  SideMenu({required this.items, required this.onItemSelected});

  
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: [
          DrawerHeader(
            decoration: BoxDecoration(
              color: Theme.of(context).primaryColor,
            ),
            child: Text(
              'Menu',
              style: TextStyle(color: Colors.white, fontSize: 24),
            ),
          ),
          ...items.map((item) => ListTile(
                leading: Icon(item.icon),
                title: Text(item.title),
                onTap: () {
                  onItemSelected(item);
                  Navigator.pop(context);
                },
              )),
        ],
      ),
    );
  }
}

class MenuItem {
  final String title;
  final IconData icon;

  MenuItem({required this.title, required this.icon});
}

Navigator

  • 説明: 画面遷移を管理します。
  • 詳細: アプリケーション内の画面遷移ロジックを管理し、ナビゲーションスタックを制御するコンポーネントです。
  • : AppNavigator, TabNavigator, StackNavigator
class AppNavigator extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Navigator(
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case '/':
            return MaterialPageRoute(builder: (_) => HomeScreen());
          case '/profile':
            return MaterialPageRoute(builder: (_) => ProfileScreen());
          case '/settings':
            return MaterialPageRoute(builder: (_) => SettingsScreen());
          default:
            return MaterialPageRoute(builder: (_) => NotFoundScreen());
        }
      },
    );
  }
}
プロフィール写真

Soraef

ソフトウェアエンジニア。趣味は競馬、写真、ゲーム。

お問い合わせはTwitterのDMでお願いします。