0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flutter(iOS向け)】ドラムロールUIで生年月日の入力 ~CupertinoDatePicker~

Last updated at Posted at 2025-01-29

はじめに

iOSアプリで生年月日を入力する際、最も一般的なUIはドラムロール式のピッカーです。
Flutterには CupertinoDatePicker というiOS標準のUIを再現できるウィジェットがあります。
本記事では CupertinoDatePicker を使って、生年月日入力を実装する方法を解説します。
Simulator Screen Recording - iPhone 16 - 2025-01-29 at 15.32.53.gif

【補足】
違う方法でのドラムロールUIで生年月日の入力の記事も掲載中です!!
ご確認いただけましたら幸いです!
https://qiita.com/_kansae_/items/8ee0725f49d7b1b400ab

目次

  1. CupertinoDatePickerとは
  2. iOSアプリにおける生年月日入力のUI
  3. CupertinoDatePickerの実装方法
  4. CupertinoDatePickerの実装方法(日本語対応)

1. CupertinoDatePickerとは

CupertinoDatePicker は、iOSのドラムロール形式の日付選択UIを提供するウィジェットです。
iOSネイティブの UIDatePicker に似ており、iPhoneユーザーに馴染みのあるデザインを実現できます。

【公式】CupertinoDatePickerについて

2. iOSアプリにおける生年月日入力の適正UI

iOSでは、生年月日はカレンダーよりもドラムロール形式のピッカーが一般的です。
この形式のメリットは以下の通りです。

  • スクロール操作で素早く日付選択が可能
  • 年、月、日を個別に選べるため間違えにくい
  • iOSユーザーが違和感なく操作できる

※あくまで一般的なので、絶対に「CupertinoDatePicker」を使用してくださいというわけではありません。

3. 今回の実装について

今回はTextFormFieldをタップするとピッカーが開く 仕様にします。
この実装では、showModalBottomSheet を使い、下からスライド表示されるモーダルで CupertinoDatePicker を表示します。
また日本語対応についての実装例も記載しておりますので参考にしていただけたらと思います。

4. CupertinoDatePickerの実装方法

以下のコードで、生年月日選択UIを実装できます。

実装コード

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // デバッグバナーを非表示に
      home: DatePickerExample(), // メイン画面をDatePickerExampleに設定
    );
  }
}

class DatePickerExample extends StatefulWidget {
  const DatePickerExample({super.key});

  @override
  _DatePickerExampleState createState() => _DatePickerExampleState();
}

class _DatePickerExampleState extends State<DatePickerExample> {
  // 生年月日を管理するためのTextEditingController
  final TextEditingController _dateController = TextEditingController();

  // 日付選択用のモーダルボトムシートを表示
  void _showDatePicker(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext builder) {
        return SizedBox(
          height: 250, // ボトムシートの高さを設定
          child: Column(
            children: [
              // CupertinoDatePicker(iOS風の日付ピッカー)
              Expanded(
                child: CupertinoDatePicker(
                  mode: CupertinoDatePickerMode.date, // 日付モードに設定
                  initialDateTime: DateTime(2000, 1, 1), // 初期日付
                  minimumDate: DateTime(1950, 1, 1), // 最小日付(1950年1月1日)
                  maximumDate: DateTime.now(), // 最大日付(今日の日付)
                  onDateTimeChanged: (DateTime newDate) {
                    // 日付変更時にテキストフィールドに反映
                    setState(() {
                      _dateController.text =
                      "${newDate.year}/${newDate.month}/${newDate.day}";
                    });
                  },
                ),
              ),
              // 完了ボタン
              TextButton(
                onPressed: () => Navigator.pop(context), // ボトムシートを閉じる
                child: Text("完了"),
              )
            ],
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('生年月日入力')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: TextFormField(
          controller: _dateController,
          readOnly: true, // タップでのみ日付選択可能
          decoration: InputDecoration(
            labelText: "生年月日",
            fillColor: Colors.white,
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(color: Colors.blue, width: 1.5),
            ),
          ),
          // フィールドがタップされた時に日付ピッカーを表示
          onTap: () => _showDatePicker(context),
        ),
      ),
    );
  }
}

5. 日本語表記にする方法

pubspec.yamlにflutter_localizationsを追記

・追記後 Pub getの実行

  flutter_localizations:
    sdk: flutter

・4のコードにflutter_localizationsで日本語表記にするコードを追記

実装コード

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
//日本語表記にするためにflutter_localizationsのインポート
import 'package:flutter_localizations/flutter_localizations.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, // デバッグバナーを非表示に
      home: DatePickerExample(), // メイン画面をDatePickerExampleに設定
      //日本語表記のためのローカライズ設定
      localizationsDelegates: [
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('ja'),
      ],
    );
  }
}

class DatePickerExample extends StatefulWidget {
  const DatePickerExample({super.key});

  @override
  _DatePickerExampleState createState() => _DatePickerExampleState();
}

class _DatePickerExampleState extends State<DatePickerExample> {
  // 生年月日を管理するためのTextEditingController
  final TextEditingController _dateController = TextEditingController();

  // 日付選択用のモーダルボトムシートを表示
  void _showDatePicker(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext builder) {
        return SizedBox(
          height: 250, // ボトムシートの高さを設定
          child: Column(
            children: [
              // CupertinoDatePicker(iOS風の日付ピッカー)
              Expanded(
                child: CupertinoDatePicker(
                  mode: CupertinoDatePickerMode.date, // 日付モードに設定
                  initialDateTime: DateTime(2000, 1, 1), // 初期日付
                  minimumDate: DateTime(1950, 1, 1), // 最小日付(1950年1月1日)
                  maximumDate: DateTime.now(), // 最大日付(今日の日付)
                  onDateTimeChanged: (DateTime newDate) {
                    // 日付変更時にテキストフィールドに反映
                    setState(() {
                      _dateController.text =
                      "${newDate.year}/${newDate.month}/${newDate.day}";
                    });
                  },
                ),
              ),
              // 完了ボタン
              TextButton(
                onPressed: () => Navigator.pop(context), // ボトムシートを閉じる
                child: Text("完了"),
              )
            ],
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('生年月日入力')),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: TextFormField(
          controller: _dateController,
          readOnly: true, // タップでのみ日付選択可能
          decoration: InputDecoration(
            labelText: "生年月日",
            fillColor: Colors.white,
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(color: Colors.blue, width: 1.5),
            ),
          ),
          // フィールドがタップされた時に日付ピッカーを表示
          onTap: () => _showDatePicker(context),
        ),
      ),
    );
  }
}

まとめ

Flutterを使用するようになりAndroidでも作成が可能という点から
iOSではどのようなUIが適切なのかより考えさせられるようになりました。
今回の生年月日入力についても、使用するターゲットや使用用途によっては
カレンダーUIの方が良かったりするのかもしれません。
絶対にこれだ!!はないと思うので臨機応変に対応できるよう
実装の知見を増やしていきたいと思う今日この頃でした👀

誤った内容がありましたらコメントお願い致します!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?