[Flutter]DrawerのリストとTabを連携させる方法

メニューバーのある項目を選択すると、タブバーの対象となる項目へ遷移する方法に1週間以上悩み続けようやく解決できました!例えばメニュバーのリスト2を選択して、タブバーの項目2を選択するようにするにはどうしたら良いのか?ハマりポイントと一緒に共有します。

ハマったポイント

  • Drawerのリストを選択して対象のタブへ飛ばない
  • 上記の対象タブへの遷移はクリアしたが、本文の部分が変更しない
  • TabViewの本文のところをスワイプできないようにしたい

やりたいこと

メニューバーの「Hotel」を選択したら、タブバーの「Hotel」に遷移するようにしたい。さらに、タブバーに紐づけられた内容のものを表示させたい。

タブバーの「Hotel」に遷移できてもBodyの部分がタブバーに紐づけられなかったところで結構時間がかかりました!

やり方

まず、Drawerの「Hotel」をタップした時にタブの「Hotel」に飛ばすには、onTap(){}に「.animateTo(インデックス)」を指定します!ちなみに、「Navigator.pop(context);」はどこにも遷移しないで前回表示していた画面へ戻ります。

drawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: Text(“ゲスト”),
decoration: BoxDecoration( color: Colors.teal,
),
),
ListTile(
onTap: (){
Navigator.pop(context);
},
title: Text(“Home”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(1);
setState(() { _selected = 1;
});
},
title: Text(“Hotel”),
trailing: Icon(Icons.keyboard_arrow_right),
),
new Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(2);
setState(() { _selected = 2;
});
},
title: Text(“Bar”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(3);
setState(() { _selected = 3;
});
},
title: Text(“Airport”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
],
),
),

「_controller.animateTo(1);」だけを指定していただけなので、対象タブには遷移するものの、本文の部分が前回表示していたままになってしまい、ここで結構つまづいていました><

解決方法は「setState」をつけるだけ!めっちゃ簡単ですね。これだけで本文も問題なく対象タブに紐付けられた本文が表示されました!

スワイプをできないようにする

また、本文の部分をスワイプできないようにしたかったので、TabBarViewの直下に「physics: NeverScrollableScrollPhysics(),」を追記して解決しました!

TabBarView(
physics: NeverScrollableScrollPhysics(),
controller: _controller,
children: <Widget>[
Icon(Icons.home, size: 200.0),
Icon(Icons.hotel, size: 200.0),
Icon(Icons.local_bar, size: 200.0),
Icon(Icons.local_airport, size: 200.0),
Icon(Icons.local_atm, size: 200.0),
],
),

フルバージョン

import ‘package:flutter/material.dart’;

void main() {
runApp(new MaterialApp(
home: new MyHomePage(),
));
}

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
TabController _controller;
int _selected = 0;

@override void initState() {
super.initState();
_controller = new TabController(length: 5, vsync: this);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘test’),
),
drawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: Text(“ゲスト”),
decoration: BoxDecoration( color: Colors.teal,
),
),
ListTile(
onTap: (){
Navigator.pop(context);
},
title: Text(“Home”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(1);
setState(() { _selected = 1;
});
},
title: Text(“Hotel”),
trailing: Icon(Icons.keyboard_arrow_right),
),
new Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(2);
setState(() { _selected = 2;
});
},
title: Text(“Bar”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
ListTile(
onTap: (){ Navigator.pop(context);
_controller.animateTo(3);
setState(() { _selected = 3;
});
},
title: Text(“Airport”),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(),
],
),
),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(color: Colors.white),
height: 80.0,
child: TabBar(
isScrollable: true,
unselectedLabelColor: Colors.grey.withOpacity(0.3),
indicatorColor: Colors.grey,
indicatorSize: TabBarIndicatorSize.label,
controller: _controller,
labelColor: Colors.grey,
onTap: (value){
_selected = value; setState(() { });
},
tabs: [
Container(
padding: EdgeInsets.only(right: 15.0,left: 15.0,top: 8.0),
child: Tab(
icon: Icon(Icons.home, size: 35.0),
text: ‘ Home ‘,
),
),
Container(
padding: EdgeInsets.only(right: 15.0,left: 15.0,top: 8.0),
child: Tab(
icon: Icon(Icons.hotel, size: 35.0),
text: ‘Hottel’,
),
),
Container(
padding: EdgeInsets.only(right: 15.0,left: 15.0,top: 8.0),
child: Tab(
icon: Icon(Icons.local_bar, size: 38.0),
text: ‘ Bar ’,
),
),
Container(
padding: EdgeInsets.only(right: 15.0,left: 15.0,top: 8.0),
child: Tab(
icon: Icon(Icons.local_airport, size: 38.0),
text: ‘Airport’,
),
),
Container(
padding: EdgeInsets.only(right: 15.0,left: 15.0,top: 8.0),
child: Tab(
icon: Icon(Icons.local_atm, size: 38.0),
text: ‘ ATM ’,
),
),
],
),
),
new Container(
padding: EdgeInsets.only(top: 40.0),
child: new TabBarView(
physics: NeverScrollableScrollPhysics(),
controller: _controller,
children: <Widget>[
Icon(Icons.home, size: 200.0),
Icon(Icons.hotel, size: 200.0),
Icon(Icons.local_bar, size: 200.0),
Icon(Icons.local_airport, size: 200.0),
Icon(Icons.local_atm, size: 200.0),
],
),
),
],
),
);
}
}

私はこのスキルを身につけて不労所得を得ています

【Web開発初心者向け!】Web開発入門完全攻略 充実の18時間コース

未経験からプロのWebデザイナーになる! 400レッスン以上の完全マスターコース

HTML/CSSだけで自動収益化 1万円達成

関連記事

[Flutter]実機でデバッグしてみる(Android編)

[Flutter]とりあえずHello Flutterコピペ

[Flutter]Providerを使ってみる

[Flutter]シンプルな折れ線グラフ

【Shopify】商品ページでスクロールするとカート追加ボタンが追従してくる方法

[flutter]実機でデバッグする方法