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

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

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

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

Dart

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

Q&A

解決済

1回答

4745閲覧

Dart/Flutterで、state外からstateを変更する方法/provider等代替方法

neoz

総合スコア31

Flutter

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

Dart

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

1グッド

1クリップ

投稿2020/09/20 00:24

前回言葉足らずだったのでhttps://teratail.com/questions/292820 続きとなります。

widget1の親画面に、widget2のカスタムナビゲーションバー(widgetなのでflutterのbottomBar機能は使えない)を取り付け、タップしたアイコンに応じて別の画面が表示されるようにしたいです。

以下のどちらかが解決策かと思っています。
・state利用してできる方法
・streamBuilderやprovider
こちらは調べてみたものの、今回のように既にstetefullで作っているものからどう移植すべきかわからず、
state利用の方法か、今回のコードに即してproviderを利用する方法/または別の方法がありましたら、ご教示いただきたいです。

widget1(親画面)

Dart

1class Homepage extends StatefulWidget { 2 3 MyAppState createState() => MyAppState(); 4} 5 6class MyAppState extends State<Homepage> { 7 int _index = 0; 8 final List<Widget> _children = [ 9 Page1(), 10 Page2(), 11 Page3(), 12 ]; 13 14 15 Widget build(BuildContext context) { 16 return Scaffold( 17 body: _children[_index], 18 bottomNavigationBar: Nav(), 19 ) 20 } 21}

widget2(ナビゲーションバー)

ここでonTapごとにint posの値が変わるので、これが変わる度に、widget1のint _indexを変更し、それによってwidget1に呼ばれる画面を変えたいです。

Dart

1class Nav extends StatefulWidget { 2 3 NavState createState() => NavState(); 4} 5 6class NavState extends State<Nav> { 7 List<NavItemClass> items = List<NavItemClass>(); 8 int pos = 0; 9 10 11 void initState() { 12 super.initState(); 13 14 items.add(NavItemClass( 15 true, 16 'assets/svg/home.svg', 17 'Home', 18 0, 19 )); 20 items.add(NavItemClass( 21 false, 22 'assets/svg/food.svg', 23 'Food', 24 1, 25 )); 26 items.add(NavItemClass( 27 false, 28 'assets/svg/weight.svg', 29 'Weight', 30 2, 31 )); 32 } 33 34 35 Widget build(BuildContext context) { 36 return Row( 37 mainAxisAlignment: MainAxisAlignment.center, 38 children: [ 39 Row( 40 children: items.map((i) { 41 return GestureDetector( 42 onTap: () { 43 setState( 44 () { 45 items.forEach((item) => item.isOpen = false); 46 i.isOpen = !i.isOpen; 47 pos = i.pos; 48 }, 49 ); 50 }, 51 child: NavItem( 52 item: i, 53 ), 54 ); 55 }).toList(), 56 ), 57 ], 58 ), 59 ), 60 ], 61 ); 62 } 63}
toast-uz👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

今回のコードに即してproviderを利用する方法/または別の方法がありましたら

providerを使って良いのであれば、以下を参考にしてください。


はじめに、providerをインストールします。

yaml

1# pubspec.yaml 2dependencies: 3 provider: ^4.3.2+1

次に、indexを管理するコントローラーを作ります。

dart

1class IndexController with ChangeNotifier { 2 int index = 0; 3 4 void setIndex(int i) { 5 this.index = i; 6 notifyListeners(); 7 } 8}

次に、Home内で

  • ChangeNotifierProviderを使って、先ほどのIndexControllerをツリー内で使用可能にする

  • Consumerで値の変更に応じて画面を更新する

ようにします。

dart

1class Home extends StatefulWidget { 2 3 _HomeState createState() => _HomeState(); 4} 5 6class _HomeState extends State<Home> { 7 final List<Widget> _children = [ 8 Page1(), 9 Page2(), 10 Page3(), 11 ]; 12 13 14 Widget build(BuildContext context) { 15 return ChangeNotifierProvider<IndexController>( 16 create: (_) => IndexController(), 17 child: Scaffold( 18 appBar: AppBar(), 19 bottomNavigationBar: Nav(), 20 body: Consumer<IndexController>( 21 builder: (context, controller, child) { 22 return _children[controller.index]; 23 }, 24 ), 25 ), 26 ); 27 } 28}

最後に、Nav内のボタンが押された時に、IndexControllersetIndex関数を呼ぶようにします。

dart

1class Nav extends StatelessWidget { 2 3 Widget build(BuildContext context) { 4 return Row( 5 children: [ 6 NavButton(index: 0), 7 NavButton(index: 1), 8 NavButton(index: 2), 9 ], 10 ); 11 } 12} 13 14class NavButton extends StatelessWidget { 15 final int index; 16 17 const NavButton({ 18 Key key, 19 this.index, 20 }) : super(key: key); 21 22 23 Widget build(BuildContext context) { 24 return RaisedButton( 25 child: Text('$index'), 26 onPressed: () { 27 context.read<IndexController>().setIndex(index); 28 }, 29 ); 30 } 31} 32

一応、手元で動作確認したコード全体を載せておきます。

dart

1import 'package:flutter/material.dart'; 2import 'package:provider/provider.dart'; 3 4class Page1 extends StatelessWidget { 5 6 Widget build(BuildContext context) { 7 return Container( 8 color: Colors.red, 9 ); 10 } 11} 12 13class Page2 extends StatelessWidget { 14 15 Widget build(BuildContext context) { 16 return Container( 17 color: Colors.amber, 18 ); 19 } 20} 21 22class Page3 extends StatelessWidget { 23 24 Widget build(BuildContext context) { 25 return Container( 26 color: Colors.purple, 27 ); 28 } 29} 30 31class IndexController with ChangeNotifier { 32 int index = 0; 33 34 void setIndex(int i) { 35 this.index = i; 36 notifyListeners(); 37 } 38} 39 40class Home extends StatefulWidget { 41 42 _HomeState createState() => _HomeState(); 43} 44 45class _HomeState extends State<Home> { 46 final List<Widget> _children = [ 47 Page1(), 48 Page2(), 49 Page3(), 50 ]; 51 52 53 Widget build(BuildContext context) { 54 return ChangeNotifierProvider<IndexController>( 55 create: (_) => IndexController(), 56 child: Scaffold( 57 appBar: AppBar(), 58 bottomNavigationBar: Nav(), 59 body: Consumer<IndexController>( 60 builder: (context, controller, child) { 61 return _children[controller.index]; 62 }, 63 ), 64 ), 65 ); 66 } 67} 68 69class Nav extends StatelessWidget { 70 71 Widget build(BuildContext context) { 72 return Row( 73 children: [ 74 NavButton(index: 0), 75 NavButton(index: 1), 76 NavButton(index: 2), 77 ], 78 ); 79 } 80} 81 82class NavButton extends StatelessWidget { 83 final int index; 84 85 const NavButton({ 86 Key key, 87 this.index, 88 }) : super(key: key); 89 90 91 Widget build(BuildContext context) { 92 return RaisedButton( 93 child: Text('$index'), 94 onPressed: () { 95 context.read<IndexController>().setIndex(index); 96 }, 97 ); 98 } 99} 100

投稿2020/09/20 01:14

nskhei

総合スコア704

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

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

neoz

2020/09/20 03:12

ありがとうございます、動きました!!金曜日あたりからnavBarに取り掛かり、やり方のわからないことばかりでずっと悩みましたが、お陰様で目指す姿になりました。 頂いたコードではボタンを実装されていたので自分のコードにどう実装すべきかわからなかったのですが 最終的にonTap: () { setState( () {context.read<IndexController>().setIndex(pos)}で動きました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問