Flutter で画面下から出てくる iOS 風ピッカー(ドラムロール)を実装します。
Flutter 1.12.13+hotfix.5
Dart 2.7.1
コード
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Modal Picker',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Modal Picker'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
_showModalPicker(context);
},
child: const Text('Show Picker'),
),
Text(_selectedItem)
],
),
),
);
}
void _showModalPicker(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height / 3,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: CupertinoPicker(
itemExtent: 40,
children: _items.map(_pickerItem).toList(),
onSelectedItemChanged: _onSelectedItemChanged,
),
),
);
},
);
}
String _selectedItem = 'none';
final List<String> _items = [
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
];
Widget _pickerItem(String str) {
return Text(
str,
style: const TextStyle(fontSize: 32),
);
}
void _onSelectedItemChanged(int index) {
setState(() {
_selectedItem = _items[index];
});
}
}
解説
CupertinoPicker を使用するため、 cupertino.dart
をインポートします。
import 'package:flutter/cupertino.dart';
ボタンをタップするとモーダル画面出てくるようにします。
モーダルの高さは画面の 3 分の 1 のサイズにしています。
showModalBottomSheet function - material library - Dart API
RaisedButton(
onPressed: () {
_showModalPicker(context);
},
// ...
),
// ...
void _showModalPicker(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height / 3,
// ...
);
},
);
}
CupertinoPicker
を GestureDetector
でラップし、ピッカー部分をタップするとモーダルが閉じるようにしています。
GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: CupertinoPicker(
// ...
)
)
itemExtent
:アイテムの高さを指定します。
children
:表示するアイテムを List<Widget>
で渡します。
onSelectedItemChanged
:アイテムが選択された際に実行する関数を指定します。
// ...
{
child: CupertinoPicker(
itemExtent: 40,
children: _items.map(_pickerItem).toList(),
onSelectedItemChanged: _onSelectedItemChanged,
),
}
// ...
String _selectedItem = 'none';
final List<String> _items = [
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
];
Widget _pickerItem(String str) {
return Text(
str,
style: const TextStyle(fontSize: 32),
);
}
void _onSelectedItemChanged(int index) {
setState(() {
_selectedItem = _items[index];
});
}