言語などの選択肢から1つを選べるドロップダウンを作り、選んだ値の取り出しと、スイッチで選べなくする切り替えまでを DropdownButtonFormField で実装できます。

アプリで言語や国を選んでもらうとき、一覧から1つを選ぶドロップダウン(プルダウン)がよく使われます。
Flutter でドロップダウンを作る部品はいくつかあります。
本記事では、フォームの仕組みにも組み込める DropdownButtonFormField を使います。画面に出す文字と、プログラムが受け取る値を分ける方法、最初に選んでおく値の決め方、選べなくする方法を、動くコードで説明します。
- Flutter でドロップダウン(プルダウン)を作りたい人
- 選択肢をリストから作る方法を知りたい人
- 画面に出す名前と、プログラムが使う値を分けたい人
- ドロップダウンを、条件によって選べなくしたい人
DropdownButtonFormField(ドロップダウン)

DropdownButtonFormField は、押すと選択肢の一覧が開き、1つを選べる部品です。公式の説明では、ドロップダウンの部品である DropdownButton を、フォームの入力欄として使えるように包んだものです。複数の入力欄をまとめて検証したいときに使う Form の中に置けますが、Form がなくても使えます。
この記事で使うプロパティは3つです。
| プロパティ | 役割 |
|---|---|
| items | 選択肢の一覧(DropdownMenuItem のリスト)。必須 |
| initialValue | 最初に選んでおく値 |
| onChanged | 選び直したときに呼ばれる関数 |
本記事では、次の動きをする画面を作ります。
- 言語の一覧から1つを選べる
- 選んだ言語の名前と ID を、ドロップダウンの下に表示する
- 「変更を許可する」スイッチをオフにすると、ドロップダウンが押せなくなる
ソースコード
- language.dart
選択肢1つ分のクラスと、一覧のデータです。
/// 選択肢1つ分。id は選んだときに渡る値、name は画面に出る文字。
class Language {
const Language(this.id, this.name);
final String id;
final String name;
}
const languages = [
Language('ja-JP', '日本語 (日本)'),
Language('en-US', 'English (United States)'),
Language('fr-FR', 'Français (France)'),
];- language_dropdown.dart
ドロップダウン部分の部品です。
import 'package:flutter/material.dart';
import '../models/language.dart';
class LanguageDropdown extends StatelessWidget {
const LanguageDropdown({
super.key,
required this.languages,
required this.selectedId,
required this.enabled,
required this.onChanged,
});
final List<Language> languages;
final String? selectedId;
final bool enabled;
final ValueChanged<String?> onChanged;
@override
Widget build(BuildContext context) {
return DropdownButtonFormField<String>(
initialValue: selectedId,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: '言語',
),
items: [
for (final language in languages)
DropdownMenuItem(value: language.id, child: Text(language.name)),
],
// onChanged が null のとき、ドロップダウンは押せなくなる。
onChanged: enabled ? onChanged : null,
);
}
}- dropdown_page.dart
画面です。選んだ値と、変更できるかどうかの状態を持ちます。
import 'package:flutter/material.dart';
import '../models/language.dart';
import '../widgets/language_dropdown.dart';
class DropdownPage extends StatefulWidget {
const DropdownPage({super.key, required this.title});
final String title;
@override
State<DropdownPage> createState() => _DropdownPageState();
}
class _DropdownPageState extends State<DropdownPage> {
String? _selectedId = languages.first.id;
bool _enabled = true;
String get _selectedName =>
languages.firstWhere((l) => l.id == _selectedId).name;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
LanguageDropdown(
languages: languages,
selectedId: _selectedId,
enabled: _enabled,
onChanged: (id) => setState(() => _selectedId = id),
),
const SizedBox(height: 12),
Text('選んだ言語: $_selectedName(ID: $_selectedId)'),
const SizedBox(height: 12),
SwitchListTile(
title: const Text('変更を許可する'),
value: _enabled,
onChanged: (value) => setState(() => _enabled = value),
),
],
),
),
);
}
}- main.dart
動かすための最小の入口です。
import 'package:flutter/material.dart';
import 'pages/dropdown_page.dart';
void main() {
runApp(
const MaterialApp(home: DropdownPage(title: 'ドロップダウン')),
);
}解説
選択肢のデータ(language.dart)、ドロップダウンの部品(language_dropdown.dart)、画面(dropdown_page.dart)を分けています。ドロップダウンの部品は、選択肢の一覧、いま選んでいる値、選べるかどうか、選び直したときの処理を、外から受け取るだけです。選んだ値は画面側が持ちます。
Language:選ぶ値と画面の文字を分ける
選択肢を、ただの文字列のリストにすることもできます。この記事では、id(プログラムが使う値)と name(画面に出す文字)の2つを持つクラスにしました。
分けておくと、画面の表示を変えても、プログラムが受け取る値が変わりません。たとえば表示を「日本語 (日本)」から「Japanese」に変えても、受け取る値は ja-JP のままです。
items:リストから選択肢を作る
items: [
for (final language in languages)
DropdownMenuItem(value: language.id, child: Text(language.name)),
],リストの中に for を書くと、一覧のデータから選択肢を作れます。DropdownMenuItem の value が、選んだときに受け取る値、child が画面に出る文字です。一覧に項目を足すだけで、選択肢も増えます。
initialValue:最初に選んでおく値
initialValue に、最初に選んでおく値を渡します。ここに渡す値は、items の value のどれか1つと一致している必要があります。
initialValue は、最初の1回に使う値です。選び直したあとの値は、onChanged で受け取って画面側で持ちます。
onChanged:選び直したときの処理と、選べなくする方法
onChanged には、選び直したときに呼ばれる関数を渡します。引数が、選ばれた value です。この画面では setState で _selectedId を更新し、下の表示を変えています。
ドロップダウンを選べなくしたいときは、onChanged に null を渡します。公式の説明では、onChanged が null のとき、ドロップダウンは無効になります。この画面では、スイッチの状態 enabled が false のときに null を渡しています。
onChanged: enabled ? onChanged : null,無効のときに出す案内文は、disabledHint で指定できます。
実装
- Flutter のプロジェクトを作る(追加するパッケージはありません)
- 3つのファイルを、上の場所に置く
- main.dart を書き換えて、実行する
ドロップダウンを押して言語を選ぶと、下の表示が変わります。スイッチをオフにすると、ドロップダウンを押せなくなります。
エラーと解決策・対策
以下では、公式の説明で示されているエラーと対処を紹介します。実際に起きたエラーではなく、起こりやすい点をまとめたものです。
There should be exactly one item with [DropdownButton]’s value
initialValue に、items の value に存在しない値を渡すと、このメッセージで止まります。公式の説明では、一致する項目がないとき、または2つ以上あるときに出ます。
- initialValue の値が、items の value のどれかと一致しているか確認する
- 同じ value の項目が2つ以上ないか確認する
- 最初は何も選ばない状態にしたいときは、initialValue を null にする
まとめ
DropdownButtonFormField は、items、initialValue、onChanged の3つを渡せば動きます。
- 選択肢は、プログラムが使う値と画面に出す文字を分けたクラスで作る
- 選択肢のリストは、リスト内の for で作る
- 最初に選んでおく値は initialValue(古い value は非推奨)
- onChanged に null を渡すと、ドロップダウンを選べなくできる

