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

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

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

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

Dart

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

Q&A

2回答

578閲覧

Flutter provider 共通化したCupertinoSegmentedを複数呼び出し、ひとつ選択するともう一つのCupertinoSegmentedも選択されてしまう。

MasatofromMGSV

総合スコア21

Flutter

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

Dart

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

0グッド

0クリップ

投稿2021/07/26 20:10

編集2021/07/26 20:19

やりたいこととできないこと
現在、tabを移動してもCupertinoSegmentedのタップした選択肢をそのままにする機能を作ろうとしています。

値の保存はでき、tabを移動しても選択したままにはできましたが、今回CupertinoSegmentedは共通化しており、ひとつ選択するともう一つのCupertinoSegmentedも選択されてしまいます。
今回はこれを無くしたいです。

コード

dart

1 2// @dart=2.9 3import 'package:flutter/material.dart'; 4import 'package:flutter/cupertino.dart'; 5import 'package:provider/provider.dart'; 6 7void main() => runApp(TabbedAppBarSample()); 8 9class TabbedAppBarSample extends StatelessWidget { 10 11 Widget build(BuildContext context) { 12 return MultiProvider( 13 providers: [ 14 ChangeNotifierProvider<SameCupertinoSegmentedControlModel>( 15 create: (context) => SameCupertinoSegmentedControlModel(), 16 ), 17 ], 18 child:MaterialApp( 19 home: DefaultTabController( 20 length: 2, 21 child: Scaffold( 22 appBar: AppBar( 23 leading: TextButton( 24 onPressed: () { 25 Navigator.of(context).pop(); 26 }, 27 child: const Text( 28 '戻る', 29 style: TextStyle( 30 color: Colors.white, //文字の色を白にする 31 fontSize: 12, //文字のサイズを調整する 32 ), 33 ), 34 ), 35 title: const Text('テスト'), 36 bottom: const TabBar( 37 labelPadding: EdgeInsets.zero, 38 tabs: [ 39 Tab(text: 'SameCupertinoSegmentedページ'), 40 Tab(text: 'テストページ'), 41 ], 42 ), 43 ), 44 body: TabBarView( 45 physics: const NeverScrollableScrollPhysics(), 46 children: [ 47 CarPage(), 48 const Icon(Icons.document_scanner), 49 ], 50 ), 51 ) 52 ) 53 ) 54 ); 55 } 56} 57 58class CarPage extends StatelessWidget { 59 60 61 Widget build(BuildContext context) { 62 return Scaffold( 63 body: Column( 64 children: [ 65 SameCupertinoSegmentedControl( 66 title: 'タイトル1', 67 value: {0: Text('value1'), 1: Text('value2')} 68 ), 69 SameCupertinoSegmentedControl( 70 title: 'タイトル2', 71 value: {0: Text('value3'), 1: Text('value4')} 72 ), 73 ], 74 ), 75 ); 76 } 77} 78 79class SameCupertinoSegmentedControl extends StatelessWidget { 80 const SameCupertinoSegmentedControl({this.title, this.value}); 81 82 final String title; 83 final Map<int, Widget> value; 84 85 86 87 Widget build(BuildContext context) { 88 final selectedValue = context.select( 89 (SameCupertinoSegmentedControlModel store) => store.selectedValue); 90 91 return Row( 92 children: [ 93 const Padding(padding: EdgeInsets.only(top: 30, bottom: 40)), 94 Container( 95 margin: const EdgeInsets.only(left: 10), 96 child: Text(title)), 97 Expanded( 98 child: CupertinoSegmentedControl( 99 children: value, 100 onValueChanged: (index) { 101 print(index); 102 context 103 .read<SameCupertinoSegmentedControlModel>() 104 .changeSelectedValue(int.parse(index.toString())); 105 }, 106 // これをひとつずつ選択できるようすれば直るはず。 107 groupValue: selectedValue 108 ) 109 ), 110 ], 111 ); 112 } 113} 114 115class SameCupertinoSegmentedControlModel with ChangeNotifier { 116 int selectedValue; 117 118 void changeSelectedValue(int index) { 119 selectedValue = index; 120 notifyListeners(); 121 } 122} 123 124

実施した手順とその結果
MultiProviderはtab間で状態を保持しておきたいため、SameCupertinoSegmentedControlではなくTabbedAppBarSampleの方に記載しています。もしSameCupertinoSegmentedControlの方にMultiProviderを定義するとやはりtab間での値の保持ができなくなってしまいます。

何が原因だと思うか
CupertinoSegmentedControl内のgroupValueを個別に設定することができれば全てに反映されないのではないかと考えましたが、そのやり方がわかりませんでした。

「CupertinoSegmentedControl groupValue 個別 」 や 「CupertinoSegmentedControl groupValue」のキーワードで検索してみたものの答えとなるような記事には辿り着けませんでした。
何かアドバイスがあればお願いします。

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

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

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

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

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

guest

回答2

0

コードの詳細な説明は後日にまた記載し直しますが、ひとまずこのコードでやりたいことであるtab間での値の保持と値がどちらにも反映されてしまう問題を解決できました。

null-safety対応に関しても後日になります。

dart

1 2// @dart=2.9 3import 'package:flutter/material.dart'; 4import 'package:flutter/cupertino.dart'; 5import 'package:provider/provider.dart'; 6 7void main() => runApp(TabbedAppBarSample()); 8 9class TabbedAppBarSample extends StatelessWidget { 10 11 Widget build(BuildContext context) { 12 return MultiProvider( 13 providers: [ 14 ChangeNotifierProvider<SameCupertinoSegmentedControlModel>( 15 create: (context) => SameCupertinoSegmentedControlModel(), 16 ), 17 ], 18 child:MaterialApp( 19 home: DefaultTabController( 20 length: 2, 21 child: Scaffold( 22 appBar: AppBar( 23 leading: TextButton( 24 onPressed: () { 25 Navigator.of(context).pop(); 26 }, 27 child: const Text( 28 '戻る', 29 style: TextStyle( 30 color: Colors.white, //文字の色を白にする 31 fontSize: 12, //文字のサイズを調整する 32 ), 33 ), 34 ), 35 title: const Text('テスト'), 36 bottom: const TabBar( 37 labelPadding: EdgeInsets.zero, 38 tabs: [ 39 Tab(text: 'SameCupertinoSegmentedページ'), 40 Tab(text: 'テストページ'), 41 ], 42 ), 43 ), 44 body: TabBarView( 45 physics: const NeverScrollableScrollPhysics(), 46 children: [ 47 CarPage(), 48 const Icon(Icons.document_scanner), 49 ], 50 ), 51 ) 52 ) 53 ) 54 ); 55 } 56} 57 58class CarPage extends StatelessWidget { 59 60 61 Widget build(BuildContext context) { 62 return Scaffold( 63 body: Column( 64 children: [ 65 SameCupertinoSegmentedControl( 66 key: ValueKey(0), 67 title: 'タイトル1', 68 value: {0: Text('value1'), 1: Text('value2')}, 69 formNumber: 0, 70 ), 71 SameCupertinoSegmentedControl( 72 key: ValueKey(1), 73 title: 'タイトル2', 74 value: {0: Text('value3'), 1: Text('value4')}, 75 formNumber: 1 76 ), 77 ], 78 ), 79 ); 80 } 81} 82 83class SameCupertinoSegmentedControl extends StatelessWidget { 84 const SameCupertinoSegmentedControl({Key key,this.title, this.value,this.formNumber}) : super(key: key); 85 86 final formNumber; 87 final String title; 88 final Map<int, Widget> value; 89 90 91 92 Widget build(BuildContext context) { 93 final selectedValue = context.select( 94 (SameCupertinoSegmentedControlModel store) => store.selectedValue); 95 // final selectedValue2 = context.select( 96 // (SameCupertinoSegmentedControlModel store) => store.selectedValue2); 97 int initialValue; 98 int initialSelectedValue(int testSelectedValue){ 99 initialValue = testSelectedValue; 100 } 101 102 return Row( 103 children: [ 104 const Padding(padding: EdgeInsets.only(top: 30, bottom: 40)), 105 Container( 106 margin: const EdgeInsets.only(left: 10), 107 child: Text(title)), 108 Expanded( 109 child: CupertinoSegmentedControl( 110 children: value, 111 onValueChanged: (index) { 112 print(index); 113 Provider.of<SameCupertinoSegmentedControlModel>(context,listen: false).changeSelectedValue(index,formNumber); 114 },(context).selectedValue 115 groupValue: Provider.of<SameCupertinoSegmentedControlModel>(context).selectedValueList[this.formNumber] 116 ) 117 ), 118 ], 119 ); 120 } 121} 122 123class SameCupertinoSegmentedControlModel with ChangeNotifier { 124 int selectedValue; 125 List<int> selectedValueList = [null,null]; 126 127 // int selectedValue2; 128 void changeSelectedValue(int index,int formNumber) { 129 switch (formNumber){ 130 case 0: 131 selectedValueList[0] = index; 132 notifyListeners(); 133 break; 134 case 1: 135 selectedValueList[1] = index; 136 notifyListeners(); 137 break; 138 } 139 } 140} 141

投稿2021/07/27 17:34

MasatofromMGSV

総合スコア21

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

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

0

SameCupertinoSegmentedControlのインスタンスは2つですが、その2つが参照しているSameCupertinoSegmentedControlModelのインスタンスが1つなので個別選択ができなくなっています。

SameCupertinoSegmentedControlModelのインスタンスを2つ作りたいところですが、Providerは同じタイプのクラスである限り、同じcontext内で1つしか持てません。

コードを大きく崩さずに解決するとすれば、

  1. CarPage内で、SameCupertinoSegmentedControlの2つのインスタンスそれぞれに対してProviderを設定する(TabbedAppBarSampleのMultiProviderは無くす)
  2. SameCupertinoSegmentedControlModelの変数の持ち方を工夫する(値の保持をMapやListにするなど)
  3. SameCupertinoSegmentedControlModelと同じようなクラス(別名)を設問ごとに作ってMultiProviderで流す

あたりが選択肢になるかと思います。

以下は 1. の場合の例です。

dart

1// MultiProviderを削除 2class TabbedAppBarSample extends StatelessWidget { 3 4 Widget build(BuildContext context) { 5 return MaterialApp( 6 home: DefaultTabController( 7 length: 2, 8 child: Scaffold( // 以下省略

dart

1// Providerを追加 2class CarPage extends StatelessWidget { 3 4 Widget build(BuildContext context) { 5 return Scaffold( 6 body: Column( 7 children: [ 8 ChangeNotifierProvider( 9 create: (context) => SameCupertinoSegmentedControlModel(), 10 child: SameCupertinoSegmentedControl( 11 title: 'タイトル1', 12 value: {0: Text('value1'), 1: Text('value2')}, 13 ), 14 ), 15 ChangeNotifierProvider( 16 create: (context) => SameCupertinoSegmentedControlModel(), 17 child: SameCupertinoSegmentedControl( 18 title: 'タイトル2', 19 value: {0: Text('value3'), 1: Text('value4')}, 20 ), 21 ), 22 ], 23 ), 24 ); 25 } 26}

投稿2021/07/27 10:34

編集2021/07/27 10:39
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

MasatofromMGSV

2021/07/27 17:30

ご回答ありがとうございます。サンプルコードまで提示していただいて大変ありがたいです。ただこれだとtab間で画面した際に、値が初期化されてしまいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問