質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

2回答

7945閲覧

bottomNavigationBarをキープして画面遷移したい

smilax

総合スコア23

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2020/08/07 02:50

前提・実現したいこと

Flutterの下タブメニューを押して、画面遷移する際にNavigationBarが消えてしまわないようキープする挙動を実現したいです。
下記の記事を参考にしながら、実装しようとするもうまくいきません。
https://qiita.com/canisterism/items/d648da85c300a3751db0

開発条件としてProviderを使用することです。
ChangeNotifierからtabBuilderに対応する値をセットしてあげたいのですが、どう設定していいかがわからずtabBuilderの部分で

The argument type 'Consumer<MyPageChangeNotifier>' can't be assigned to the parameter type 'Widget Function(BuildContext, int)'.

とエラーがでてしまいます。



flutter

1import 'package:flutter/material.dart'; 2import 'package:flutter/cupertino.dart'; 3import 'package:flutter/widgets.dart'; 4import 'package:provider/provider.dart'; 5 6import 'MyPageChangeNotifier.dart'; 7import 'package:talent/view/screen/myPage/component/Profile.dart'; 8import 'package:talent/view/screen/myPage/component/RequestStatus.dart'; 9import 'package:talent/view/component/Header.dart'; 10import 'package:talent/PresentIcon.dart'; 11import 'package:talent/SettingIcon.dart'; 12import 'package:talent/view/screen/myPage/component/NoticeItem.dart'; 13// import 'package:talent/view/component/BorderedText.dart'; 14 15class MyPageScreen extends StatelessWidget { 16 @override 17 Widget build(BuildContext context) { 18 return ChangeNotifierProvider<MyPageChangeNotifier>( 19 create: (context) => MyPageChangeNotifier(), 20 child: CupertinoTabScaffold( 21 tabBar: CupertinoTabBar( 22 items: <BottomNavigationBarItem>[ 23 BottomNavigationBarItem(icon: Icon(Icons.face), title: Text('タレント')), 24 BottomNavigationBarItem(icon: Icon(PresentIcon.present_icon), title: Text('リクエスト')), 25 BottomNavigationBarItem(icon: Icon(SettingIcon.setting_icon), title: Text('設定')), 26 ], 27 currentIndex: currentIndex, 28 onTap: (n) { 29 switch (n) { 30 case 0: 31 onTapItem(TabItem.Talent); 32 currentIndex = TabItem.Talent.index; 33 break; 34 case 1: 35 onTapItem(TabItem.Message); 36 currentIndex = TabItem.Message.index; 37 break; 38 case 2: 39 onTapItem(TabItem.Setting); 40 currentIndex = TabItem.Setting.index; 41 break; 42 } 43 } 44 ), 45 tabBuilder: Consumer<MyPageChangeNotifier>(builder: (context, value, child) { 46 value.navigation(context, tabItem) 47 });  //エラー箇所 48 body: Consumer<MyPageChangeNotifier>( 49 builder: (context, value, child) { 50 return SingleChildScrollView( 51 child: Column( 52 children: <Widget>[ 53 Container( 54 color: Color(0xffF5F6F9), 55 child: Padding( 56 padding: EdgeInsets.only(top: 40.0, bottom: 60.0, right: 40.0, left: 40.0), 57 child: Column( 58 children: <Widget>[ 59 Profile(), 60 SizedBox(height: 20.0), 61 RequestStatus(), 62 ], 63 ), 64 ), 65 ), 66 Padding( 67 padding: EdgeInsets.only(top: 40.0, right: 24.0, left: 24.0, bottom: 63.0), 68 child: Column(children: <Widget>[ 69 // BorderedText(text: "お知らせ"), 70 SizedBox(height: 24.0), 71 NoticeItem(text: value.text, date: value.date), 72 SizedBox(height: 20.0), 73 NoticeItem(text: value.text, date: value.date), 74 ]), 75 ), 76 ], 77 ), 78 ); 79 }, 80 ), 81 ) 82 ); 83 } 84}

Provider

flutter

1import 'package:flutter/cupertino.dart'; 2import 'package:talent/view/screen/myPage/MyPageScreen.dart'; 3 4enum TabItem { 5 Talent, 6 Message, 7 Setting, 8} 9 10class MyPageChangeNotifier with ChangeNotifier { 11 String _date = "2020.XX.XX"; 12 String _text = "お知らせお知らせお知らせお知らせお知らせお知らせお知らせお知らせお知らせお知らせお知らせお知らせ。"; 13 14 get date => _date; 15 get text => _text; 16 17 Widget (TabItem tabItem) { 18 switch (tabItem) { 19 case TabItem.Talent: // 1番左のタブが選ばれた時の画面 20 return CupertinoTabView(builder: (context) { 21 return CupertinoPageScaffold( 22 child: MyPageScreen(), // 表示したい画面のWidget 23 ); 24 }); 25 break; 26 case TabItem.Message: // 1番左のタブが選ばれた時の画面 27 CupertinoTabView(builder: (context) { 28 return CupertinoPageScaffold( 29 child: MyPageScreen(), // 表示したい画面のWidget 30 ); 31 }); 32 break; 33 case TabItem.Setting: // 1番左のタブが選ばれた時の画面 34 CupertinoTabView(builder: (context) { 35 return CupertinoPageScaffold( 36 child: MyPageScreen(), // 表示したい画面のWidget 37 ); 38 }); 39 break; 40 } 41 return null; 42 } 43} 44

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

(追記)
https://qiita.com/canisterism/items/d648da85c300a3751db0
の内容を読まずに最初の回答をしましたが

Navigator.of(context).pushを行ったときに消える動作を防ぎたいということでしたら、まず、上記URLにもあるとおりですが、とくになにもせずにNavigator.of(context)を行うと最も上位のWidgetが置き換わってしまうためにNaviBarが消えてしまいます。

なので、「常にNaviBarを表示しておきたい」という場合には上記例のtabBuilderにNavigatorを含んでおけばよいということになります。

ただし、CupertinoTabScaffoldではTab間の移動には基本的にNavigator.of(context)を使わないように思うので、これはあくまで「別のページを表示する」ときにも「常に元のページのNaviBarを表示しておきたい」ときの操作だと考えます。使用シーンがイマイチわかりませんが、一応、簡単に書けるので、設定のタブから別のページへの遷移をもとのページのTabを維持したまま行う例を以下に示します。

dart

1import 'package:flutter/foundation.dart'; 2import 'package:flutter/material.dart'; 3import 'package:flutter/cupertino.dart'; 4import 'package:provider/provider.dart'; 5 6void main() { 7 runApp(const MyApp()); 8} 9 10class MyApp extends StatelessWidget { 11 const MyApp({Key key}) : super(key: key); 12 // This widget is the root of your application. 13 14 Widget build(BuildContext context) { 15 return MaterialApp( 16 title: 'Flutter Demo', 17 theme: ThemeData( 18 primarySwatch: Colors.blue, 19 visualDensity: VisualDensity.adaptivePlatformDensity, 20 ), 21 home: Scaffold( 22 body: ChangeNotifierProvider<_NavigatorHistoryStore>( 23 create: (_) => _NavigatorHistoryStore(), 24 child: const MainPage())), 25 ); 26 } 27} 28 29const int talentTabIndex = 0; 30const int requestTabIndex = 1; 31const int settingTabIndex = 2; 32 33class MainPage extends StatelessWidget { 34 const MainPage({Key key}) : super(key: key); 35 36 37 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 38 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => 39 CupertinoTabScaffold( 40 controller: navi.controller, 41 tabBar: CupertinoTabBar(items: const <BottomNavigationBarItem>[ 42 BottomNavigationBarItem( 43 icon: Icon(Icons.face), title: Text('タレント')), 44 BottomNavigationBarItem( 45 icon: Icon(Icons.mail), title: Text('リクエスト')), 46 BottomNavigationBarItem( 47 icon: Icon(Icons.settings), title: Text('設定')), 48 ]), 49 tabBuilder: (BuildContext context, int index) => Navigator( 50 initialRoute: 'main/tabs', 51 onGenerateRoute: (RouteSettings settings) => 52 MaterialPageRoute<PageRoute<Widget>>( 53 settings: settings, 54 builder: (_) => const <Widget>[ 55 _TalentTabPage(), 56 _RequestTabPage(), 57 _SettingTabPage(), 58 ][index])))); 59} 60 61class _TalentTabPage extends StatelessWidget { 62 const _TalentTabPage({Key key}) : super(key: key); 63 64 65 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 66 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 67 mainAxisAlignment: MainAxisAlignment.center, 68 children: <Widget>[ 69 const Text('タレントのタブです'), 70 RaisedButton( 71 child: const Text('リクエストを表示'), 72 onPressed: () => navi.moveTo(requestTabIndex)), 73 RaisedButton( 74 child: const Text('設定を表示'), 75 onPressed: () => navi.moveTo(settingTabIndex)), 76 RaisedButton( 77 child: const Text('もどる'), 78 onPressed: navi.hasHistory ? navi.pop : null), 79 ])); 80} 81 82class _RequestTabPage extends StatelessWidget { 83 const _RequestTabPage({Key key}) : super(key: key); 84 85 86 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 87 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 88 mainAxisAlignment: MainAxisAlignment.center, 89 children: <Widget>[ 90 const Text('リクエストのタブです'), 91 RaisedButton( 92 child: const Text('タレントを表示'), 93 onPressed: () => navi.moveTo(talentTabIndex)), 94 RaisedButton( 95 child: const Text('設定を表示'), 96 onPressed: () => navi.moveTo(settingTabIndex)), 97 RaisedButton( 98 child: const Text('もどる'), 99 onPressed: navi.hasHistory ? navi.pop : null), 100 ])); 101} 102 103class _SettingTabPage extends StatelessWidget { 104 const _SettingTabPage({Key key}) : super(key: key); 105 106 107 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 108 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 109 mainAxisAlignment: MainAxisAlignment.center, 110 children: <Widget>[ 111 const Text('設定のタブです'), 112 RaisedButton( 113 child: const Text('別のページを開く'), 114 onPressed: () => Navigator.of(context).push( 115 MaterialPageRoute<PageRoute<Widget>>( 116 builder: (_) => _OtherPage()))), 117 RaisedButton( 118 child: const Text('もどる'), 119 onPressed: navi.hasHistory ? navi.pop : null), 120 ])); 121} 122 123class _NavigatorHistoryStore extends ChangeNotifier { 124 _NavigatorHistoryStore() { 125 controller.addListener(push); 126 } 127 final CupertinoTabController controller = CupertinoTabController(); 128 129 int _prevIndex = 0; 130 bool _onPop = false; 131 List<int> histories = <int>[]; 132 bool get hasHistory => histories.isNotEmpty; 133 134 135 void dispose() { 136 controller.dispose(); 137 super.dispose(); 138 } 139 140 void moveTo(int index) { 141 if (controller.index == index) { 142 return; 143 } 144 controller.index = index; 145 } 146 147 void push() { 148 if (_prevIndex == controller.index) { 149 return; 150 } 151 if (_onPop) { 152 _onPop = false; 153 } else { 154 histories.add(_prevIndex); 155 } 156 _prevIndex = controller.index; 157 notifyListeners(); 158 } 159 160 void pop() { 161 _onPop = true; 162 if (histories.isNotEmpty) { 163 controller.index = histories.removeLast(); 164 } 165 } 166} 167 168class _OtherPage extends StatelessWidget { 169 170 Widget build(BuildContext context) => Scaffold( 171 body: Center( 172 child: Column( 173 mainAxisAlignment: MainAxisAlignment.center, 174 children: <Widget>[ 175 const Text('これば別のページ'), 176 RaisedButton( 177 child: const Text('もとのページに戻る'), 178 onPressed: () => Navigator.of(context).pop()), 179 ]))); 180} 181

投稿2020/08/13 13:39

aya-eiya

総合スコア97

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ワンファイルで示せるように極力小さなコード例を示します。

質問の「Flutterの下タブメニューを押して、画面遷移する際にNavigationBarが消えてしまわないようキープする挙動を実現したいです」ということであれば、以下のようにすれば大丈夫です。

この目的のためにProviderを使う必要はありません。

dart

1import 'package:flutter/foundation.dart'; 2import 'package:flutter/material.dart'; 3import 'package:flutter/cupertino.dart'; 4 5void main() { 6 runApp(const MyApp()); 7} 8 9class MyApp extends StatelessWidget { 10 const MyApp({Key key}):super(key:key); 11 // This widget is the root of your application. 12 13 Widget build(BuildContext context) { 14 return MaterialApp( 15 title: 'Flutter Demo', 16 theme: ThemeData( 17 primarySwatch: Colors.blue, 18 visualDensity: VisualDensity.adaptivePlatformDensity, 19 ), 20 home: const Scaffold(body: MainPage()), 21 ); 22 } 23} 24 25class MainPage extends StatelessWidget { 26 const MainPage({Key key}) : super(key: key); 27 28 29 Widget build(BuildContext context) => CupertinoTabScaffold( 30 tabBar: CupertinoTabBar(items: const <BottomNavigationBarItem>[ 31 BottomNavigationBarItem(icon: Icon(Icons.face), title: Text('タレント')), 32 BottomNavigationBarItem(icon: Icon(Icons.mail), title: Text('リクエスト')), 33 BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text('設定')), 34 ]), 35 tabBuilder: (BuildContext context, int index) => const <Widget>[ 36 _TalentTabPage(), 37 _RequestTabPage(), 38 _SettingTabPage(), 39 ][index]); 40} 41 42class _TalentTabPage extends StatelessWidget { 43 const _TalentTabPage({Key key}) : super(key: key); 44 45 46 Widget build(BuildContext context) => const Center(child: Text('タレントのタブです')); 47} 48 49class _RequestTabPage extends StatelessWidget { 50 const _RequestTabPage({Key key}) : super(key: key); 51 52 53 Widget build(BuildContext context) => const Center(child: Text('リクエストのタブです')); 54} 55 56class _SettingTabPage extends StatelessWidget { 57 const _SettingTabPage({Key key}) : super(key: key); 58 59 60 Widget build(BuildContext context) => const Center(child: Text('設定のタブです')); 61}

CupertinoTabScaffoldが色々と世話を焼いてくれるので、ProviderなどによるcurrentIndexの管理は不要です。

ただし、履歴を保管したい場合やを他のWidgetからNaviを操作したい場合などには以下のようにcontrollerを持つProviderを提供することもあります。

dart

1import 'package:flutter/foundation.dart'; 2import 'package:flutter/material.dart'; 3import 'package:flutter/cupertino.dart'; 4import 'package:provider/provider.dart'; 5 6void main() { 7 runApp(const MyApp()); 8} 9 10class MyApp extends StatelessWidget { 11 const MyApp({Key key}) : super(key: key); 12 // This widget is the root of your application. 13 14 Widget build(BuildContext context) { 15 return MaterialApp( 16 title: 'Flutter Demo', 17 theme: ThemeData( 18 primarySwatch: Colors.blue, 19 visualDensity: VisualDensity.adaptivePlatformDensity, 20 ), 21 home: Scaffold( 22 body: ChangeNotifierProvider<_NavigatorHistoryStore>( 23 create: (_) => _NavigatorHistoryStore(), 24 child: const MainPage())), 25 ); 26 } 27} 28 29const int talentTabIndex = 0; 30const int requestTabIndex = 1; 31const int settingTabIndex = 2; 32 33class MainPage extends StatelessWidget { 34 const MainPage({Key key}) : super(key: key); 35 36 37 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 38 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => 39 CupertinoTabScaffold( 40 controller: navi.controller, 41 tabBar: CupertinoTabBar(items: const <BottomNavigationBarItem>[ 42 BottomNavigationBarItem( 43 icon: Icon(Icons.face), title: Text('タレント')), 44 BottomNavigationBarItem( 45 icon: Icon(Icons.mail), title: Text('リクエスト')), 46 BottomNavigationBarItem( 47 icon: Icon(Icons.settings), title: Text('設定')), 48 ]), 49 tabBuilder: (BuildContext context, int index) => const <Widget>[ 50 _TalentTabPage(), 51 _RequestTabPage(), 52 _SettingTabPage(), 53 ][index])); 54} 55 56class _TalentTabPage extends StatelessWidget { 57 const _TalentTabPage({Key key}) : super(key: key); 58 59 60 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 61 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 62 mainAxisAlignment: MainAxisAlignment.center, 63 children: <Widget>[ 64 const Text('タレントのタブです'), 65 RaisedButton( 66 child: const Text('リクエストを表示'), 67 onPressed: () => navi.moveTo(requestTabIndex)), 68 RaisedButton( 69 child: const Text('設定を表示'), 70 onPressed: () => navi.moveTo(settingTabIndex)), 71 RaisedButton( 72 child: const Text('もどる'), 73 onPressed: navi.hasHistory ? navi.pop : null), 74 ])); 75} 76 77class _RequestTabPage extends StatelessWidget { 78 const _RequestTabPage({Key key}) : super(key: key); 79 80 81 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 82 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 83 mainAxisAlignment: MainAxisAlignment.center, 84 children: <Widget>[ 85 const Text('リクエストのタブです'), 86 RaisedButton( 87 child: const Text('タレントを表示'), 88 onPressed: () => navi.moveTo(talentTabIndex)), 89 RaisedButton( 90 child: const Text('設定を表示'), 91 onPressed: () => navi.moveTo(settingTabIndex)), 92 RaisedButton( 93 child: const Text('もどる'), 94 onPressed: navi.hasHistory ? navi.pop : null), 95 ])); 96} 97 98class _SettingTabPage extends StatelessWidget { 99 const _SettingTabPage({Key key}) : super(key: key); 100 101 102 Widget build(BuildContext context) => Consumer<_NavigatorHistoryStore>( 103 builder: (BuildContext context, _NavigatorHistoryStore navi, _) => Column( 104 mainAxisAlignment: MainAxisAlignment.center, 105 children: <Widget>[ 106 const Text('設定のタブです'), 107 RaisedButton( 108 child: const Text('もどる'), 109 onPressed: navi.hasHistory ? navi.pop : null), 110 ])); 111} 112 113class _NavigatorHistoryStore extends ChangeNotifier { 114 _NavigatorHistoryStore() { 115 controller.addListener(push); 116 } 117 final CupertinoTabController controller = CupertinoTabController(); 118 119 int _prevIndex = 0; 120 bool _onPop = false; 121 List<int> histories = <int>[]; 122 bool get hasHistory => histories.isNotEmpty; 123 124 125 void dispose() { 126 controller.dispose(); 127 super.dispose(); 128 } 129 130 void moveTo(int index) { 131 if (controller.index == index) { 132 return; 133 } 134 controller.index = index; 135 } 136 137 void push() { 138 if (_prevIndex == controller.index) { 139 return; 140 } 141 if (_onPop) { 142 _onPop = false; 143 } else { 144 histories.add(_prevIndex); 145 } 146 _prevIndex = controller.index; 147 notifyListeners(); 148 } 149 150 void pop() { 151 _onPop = true; 152 if (histories.isNotEmpty) { 153 controller.index = histories.removeLast(); 154 } 155 } 156}

投稿2020/08/13 12:48

aya-eiya

総合スコア97

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

同じタグがついた質問を見る

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。