Flutter ユーザー入力

このセクションでは、Flutter アプリでユーザー入力を処理する方法について説明します。テキスト入力、ボタンクリック、フォーム処理などが含まれます。


TextField - テキスト入力

TextField は Flutter で最もよく使われるテキスト入力ウィジェットです。

例:TextField 基本的な使い方

// 最も簡単な TextField
TextField()

// 装飾付きの TextField
TextField(
  decoration: const InputDecoration(
    labelText: 'ユーザー名',  // ラベル
    hintText: 'ユーザー名を入力してください',  // プレースホルダー
    prefixIcon: Icon(Icons.person),  // 前置きアイコン
  ),
)

// 枠線付きの TextField
TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(  // 外枠
      borderRadius: BorderRadius.circular(8),
    ),
    labelText: 'パスワード',
  ),
  obscureText: true,  // 入力を隠す(パスワード場面)
)

// 複数行テキスト入力
TextField(
  maxLines: 3,  // 最大行数
  decoration: const InputDecoration(
    hintText: '複数行テキストを入力してください',
  ),
)

TextEditingController - テキストコントローラー

TextEditingController を使用すると、TextField の内容を読み取り・制御できます。

< h2 class="example">例:TextEditingController の使い方
class TextFieldExample extends StatefulWidget {
  const TextFieldExample({super.key});

  @override
  State<TextFieldExample> createState() => _TextFieldExampleState();
}

class _TextFieldExampleState extends State<TextFieldExample> {
  // コントローラーを作成
  final TextEditingController _controller = TextEditingController();
  String _displayText = '';

  @override
  void dispose() {
    // コントローラーを破棄
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          controller: _controller,  // コントローラーをバインド
          decoration: const InputDecoration(
            labelText: 'テキストを入力',
          ),
          onChanged: (text) {
            // テキストの変更を監視
            print('現在の入力: $text');
          },
        ),
        const SizedBox(height: 20),
        // 入力されたテキストを表示
        Text('あなたが入力した: $_displayText'),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: () {
            // テキストを読み取る
            setState(() {
              _displayText = _controller.text;
            });
          },
          child: const Text('入力を表示'),
        ),
        ElevatedButton(
          onPressed: () {
            // テキストをクリア
            _controller.clear();
          },
          child: const Text('クリア'),
        ),
        ElevatedButton(
          onPressed: () {
            // テキストを設定
            _controller.text = 'プリセットテキスト';
          },
          child: const Text('テキストを設定'),
        ),
      ],
    );
  }
}

フォーカス制御

FocusNode を使用すると、入力フィールドのフォーカスを制御できます。

例:フォーカス制御

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

  @override
  State<FocusExample> createState() => _FocusExampleState();
}

class _FocusExampleState extends State<FocusExample> {
  final FocusNode _focusNode1 = FocusNode();
  final FocusNode _focusNode2 = FocusNode();

  @override
  void dispose() {
    _focusNode1.dispose();
    _focusNode2.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          focusNode: _focusNode1,
          decoration: const InputDecoration(labelText: '入力フィールド 1'),
        ),
        const SizedBox(height: 10),
        TextField(
          focusNode: _focusNode2,
          decoration: const InputDecoration(labelText: '入力フィールド 2'),
        ),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: () {
            // 入力フィールド 1 にフォーカス
            _focusNode1.requestFocus();
          },
          child: const Text('入力フィールド 1 にフォーカス'),
        ),
        ElevatedButton(
          onPressed: () {
            // 入力フィールド 2 にフォーカス
            _focusNode2.requestFocus();
          },
          child: const Text('入力フィールド 2 にフォーカス'),
        ),
        ElevatedButton(
          onPressed: () {
            // フォーカスを外す
            _focusNode1.unfocus();
            _focusNode2.unfocus();
          },
          child: const Text('フォーカスを外す'),
        ),
      ],
    );
  }
}

ボタンとクリックイベント

Flutter は、ユーザーのクリックを処理するためのさまざまなボタンウィジェットを提供します。

例:各種ボタン

// TextButton - テキストボタン
TextButton(
  onPressed: () => print('テキストボタンがクリックされました'),
  child: const Text('テキストボタン'),
)

// ElevatedButton - 浮き出たボタン
ElevatedButton(
  onPressed: () => print('浮き出たボタンがクリックされました'),
  child: const Text('送信'),
)

// OutlinedButton - アウトラインボタン
OutlinedButton(
  onPressed: () => print('アウトラインボタンがクリックされました'),
  child: const Text('キャンセル'),
)

// IconButton - アイコンボタン
IconButton(
  icon: const Icon(Icons.favorite),
  onPressed: () => print('アイコンボタンがクリックされました'),
)

// アイコン付きボタン
ElevatedButton.icon(
  onPressed: () => print('アイコン付きボタンがクリックされました'),
  icon: const Icon(Icons.save),
  label: const Text('保存'),
)

// CupertinoButton - iOS スタイルボタン
CupertinoButton(
  child: const Text('iOS ボタン'),
  onPressed: () {},
)

Switch、Checkbox、Radio

例:スイッチ、チェックボックス、ラジオボタン

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

  @override
  State<SwitchCheckboxExample> createState() => _SwitchCheckboxExampleState();
}

class _SwitchCheckboxExampleState extends State<SwitchCheckboxExample> {
  bool _switchValue = false;
  bool _checkboxValue = false;
  String _radioValue = 'A';

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // Switch スイッチ
        Switch(
          value: _switchValue,
          onChanged: (value) {
            setState(() {
              _switchValue = value;
            });
          },
        ),
        Text('Switch 値: $_switchValue'),

        // Checkbox チェックボックス
        Checkbox(
          value: _checkboxValue,
          onChanged: (value) {
            setState(() {
              _checkboxValue = value ?? false;
            });
          },
        ),
        Text('Checkbox 値: $_checkboxValue'),

        // Radio ラジオボタン
        Row(
          children: [
            Radio<String>(
              value: 'A',
              groupValue: _radioValue,
              onChanged: (value) {
                setState(() {
                  _radioValue = value!;
                });
              },
            ),
            const Text('オプション A'),
            Radio<String>(
              value: 'B',
              groupValue: _radioValue,
              onChanged: (value) {
                setState(() {
                  _radioValue = value!;
                });
              },
            ),
            const Text('オプション B'),
          ],
        ),
        Text('Radio 値: $_radioValue'),
      ],
    );
  }
}

Slider - スライダー

例:Slider の使い方

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

  @override
  State<SliderExample> createState() => _SliderExampleState();
}

class _SliderExampleState extends State<SliderExample> {
  double _sliderValue = 0.5;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Slider(
          value: _sliderValue,  // 現在値(0.0-1.0)
          min: 0.0,
          max: 1.0,
          divisions: 10,  // 10 目盛りに分割
          label: '${(_sliderValue * 100).round()}%',
          onChanged: (value) {
            setState(() {
              _sliderValue = value;
            });
          },
        ),
        Text('現在値: ${(_sliderValue * 100).round()}%'),

        // 範囲スライダー
        RangeSlider(
          values: const RangeValues(0.3, 0.7),
          min: 0.0,
          max: 1.0,
          onChanged: (values) {
            print('範囲: ${values.start} - ${values.end}');
          },
        ),
      ],
    );
  }
}

ユーザー入力を処理するときは、setState を使用して UI 状態を更新することを忘れないでください。そうすることで、インターフェースがユーザーの操作に応答できるようになります。

その他の拡張