はじめに
FlutterのDrawer(ドロワー)1について調べたことを書きます。基本構成は公式2に任せます。
実装
コード側の処理によって開く3
デフォルトで実装されるメニューボタンから別のボタンに変えたい時に使えます。以下のどちらかを使えば実装できます。
_key.currentState.openDrawer()
Scaffold.of(context).openDrawer()
コード内ではボタンによってドロワーが開く様になっています。
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
drawerEdgeDragWidth: 0, // ボタンのみでドロワーを開ける様にする(スワイプでドロワーを開けるエリアを0にする)
drawer: Drawer(),
appBar: AppBar(
automaticallyImplyLeading: false, // デフォルトで設置されるメニューボタンを表示させない
),
body: Center(
child: RaisedButton(
child: Text('open'),
onPressed: () => _key.currentState.openDrawer(),
)));
}
コード側の処理によって閉じる24
Navigatorを使えば実装できます。
Navigator.pop(context)
コード内ではIconButton(X)のタップでドロワーが閉じるようにしています。
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
drawerEdgeDragWidth: 0, // ボタンのみでドロワーを開ける様にする(スワイプでドロワーを開けるエリアを0にする)
drawer: Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Drawer Header'),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.pop(context),
)
]),
decoration: BoxDecoration(
color: Colors.blue,
))
])),
appBar: AppBar(
automaticallyImplyLeading: false, // デフォルトで設置されるメニューボタンを表示させない
),
body: Center(
child: RaisedButton(
child: Text('open'),
onPressed: () => _key.currentState.openDrawer(),
)));
}
バックボタンで閉じる4
Androidだとバックボタンでドロワーを閉じたい時があると思います。その時はScaffoldをWillPopScopeで囲って上げます。
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
bool isDrawerOpen = _key.currentState.isDrawerOpen;
if (isDrawerOpen) {
Navigator.pop(context);
return Future.value(false); // 画面遷移をさせない
} else {
return Future.value(true); // 画面遷移を許可
}
},
child: Scaffold(...)); // drawerの中身
}
幅を設定する5
drawerが開いたときの幅を設定します。SizedBoxなどの幅を設定できるWidgetで囲ってあげます。
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: SizedBox(width: 100, child: Drawer()), // 幅が100になる
appBar: AppBar(),
}
実装自体と関係ないですがDrawer自体は開発者としては便利ですが、中の項目が隠れてしまい別の画面に遷移するのに一手間かかる6ので実装する際に考慮する必要はあるようです。