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

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

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

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

Dart

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

Q&A

解決済

1回答

1560閲覧

Flutter RangeSliderをポップアップ状態で実施すると、スライドバーが動作しない。

takumi123

総合スコア59

Flutter

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

Dart

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

0グッド

0クリップ

投稿2020/09/26 18:09

編集2020/09/26 23:28

問題

Flutterで以下のRangeSlidebarをStatelessWidgetコード内で作成しています。
https://api.flutter.dev/flutter/material/RangeSlider-class.html

しかし、ポップアップ状態ではスライドバーが動作しません。
どのようにすれば良いでしょうか?

#補足イメージ
検索フィルタ用のスライドバーをポップアップで実施しています。

イメージ説明

以下は一度ポップアップを閉じて、再度開いた状態です。
値の変更は反映されていますが、スライドバーは動かず、一度閉じないといけません。

イメージ説明

#コード

以下は表示側のコード

dart

1class MapsHome extends StatelessWidget { 2Widget build(BuildContext context) { 3 return ChangeNotifierProvider( 4 create: (_) => MapHome(this.uid), 5 child: Consumer<MapHome>( 6 builder: (BuildContext context, model, child) => Scaffold(   7    ・ 8    ・ 9    ・ 10IconButton( 11 color: Colors.black54, 12 icon: Icon(Icons.filter_list, 13 onPressed: () async { 14 if (await openSearchSetting(context, model) =="yes") { 15 //検索フィルタ適用後の処理 16 } 17 }, 18), 19  ・ 20  ・ 21  ・ 22 //検索フィルタのポップアップ処理。 23 Future<String> openSearchSetting(BuildContext context, MapHome model) async { 24 String value = await showDialog<String>( 25 context: context, 26 builder: (BuildContext context) => new SimpleDialog( 27 title: new Text("検索フィルタ", style: TextStyle(fontSize: 17)), 28 children: <Widget>[ 29 Padding( 30 padding: EdgeInsets.fromLTRB(0, 0, 0, 5), 31 child: new Divider(), 32 ), 33 Padding( 34 padding: EdgeInsets.fromLTRB(30, 0, 30, 0), 35 child: Row( 36 mainAxisAlignment: MainAxisAlignment.start, 37 children: [ 38 Text( 39 "評価", 40 style: TextStyle(fontSize: 14), 41 ), 42 RangeSlider( 43 values: model.currentRangeValues, 44 min: 0, 45 max: 10, 46 divisions: 10, 47 labels: RangeLabels( 48 model.currentRangeValues.start.round().toString(), 49 model.currentRangeValues.end.round().toString(), 50 ), 51 onChanged: (RangeValues values) { 52 model.ChangeSearchStarRange(values); 53 }, 54 ), 55 ], 56 ), 57 ), 58 Padding( 59 padding: EdgeInsets.fromLTRB(0, 0, 0, 5), 60 child: new Divider(), 61 ), 62 Row( 63 mainAxisAlignment: MainAxisAlignment.end, 64 children: [ 65 createDialogOption(context, "no", "キャンセル"), 66 createDialogOption(context, "yes", "適用"), 67 ], 68 ), 69 ], 70 ), 71 ); 72 73 return value; 74 } 75 76}

以下は処理側のコード

dart

1class MapHome extends ChangeNotifier { 2 RangeValues currentRangeValues = const RangeValues(0, 10); 3 void ChangeSearchStarRange(RangeValues values) { 4 this.currentRangeValues = values; 5 notifyListeners(); 6 } 7} 8

#補足
RangeSlidebarのサンプルではsetState()で値を更新しています。しかし、私はStatelessWidegetで作成しています。statefullwidget変更の修正範囲の関係からできる限りStatelessWidgetのまま実装の方法を探しています。
https://api.flutter.dev/flutter/material/RangeSlider-class.html

#追記
nskhei様の回答を受けて、追加質問です。

showDialogを動作させるにはChangeNotifierProviderを新たに作成する必要がある。
このshowDialogは検索フィルターで、閉じた先にあるChangeNotifierProviderのインスタンスに値を渡したいと考えています。

新たにChangeNotifierProviderを作成すると、別個のインスタンスになり、値を引き継げないと考えているのですが、どのようにすればよろしいでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

showDialogは画面遷移と同じなので、元ページにあるConsumerによるリビルドは効きません。

ダイアログ内で再度ChangeNotifierProvider + Consumerを設置することで、解決すると思います。

dart

1 Future<String> openSearchSetting(BuildContext context, MapHome model) async { 2 String value = await showDialog<String>( 3 context: context, 4 builder: (BuildContext context) => ChangeNotifierProvider<MapHome>.value( 5 value: model, 6 child: new SimpleDialog( 7 title: new Text("検索フィルタ", style: TextStyle(fontSize: 17)), 8 children: <Widget>[ 9 Padding( 10 padding: EdgeInsets.fromLTRB(0, 0, 0, 5), 11 child: new Divider(), 12 ), 13 Padding( 14 padding: EdgeInsets.fromLTRB(30, 0, 30, 0), 15 child: Row( 16 mainAxisAlignment: MainAxisAlignment.start, 17 children: [ 18 Text( 19 "評価", 20 style: TextStyle(fontSize: 14), 21 ), 22 Consumer<MapHome>( 23 builder: (context, model, child) { 24 return RangeSlider( 25 values: model.currentRangeValues, 26 min: 0, 27 max: 10, 28 divisions: 10, 29 labels: RangeLabels( 30 model.currentRangeValues.start.round().toString(), 31 model.currentRangeValues.end.round().toString(), 32 ), 33 onChanged: (RangeValues values) { 34 model.ChangeSearchStarRange(values); 35 }, 36 ); 37 }, 38 ), 39 ], 40 ), 41 ), 42 Padding( 43 padding: EdgeInsets.fromLTRB(0, 0, 0, 5), 44 child: new Divider(), 45 ), 46 Row( 47 mainAxisAlignment: MainAxisAlignment.end, 48 children: [ 49 createDialogOption(context, "no", "キャンセル"), 50 createDialogOption(context, "yes", "適用"), 51 ], 52 ), 53 ], 54 ), 55 ), 56 ); 57 return value; 58 }

投稿2020/09/26 22:53

nskhei

総合スコア704

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

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

takumi123

2020/09/26 23:26

回答ありがとうございます。 なるほど、ChangeNotifierProviderを新たに作成する必要があるのですね。 このshowDialogは検索フィルターで、閉じた先にあるChangeNotifierProviderに値を渡したいと考えています。 新たにChangeNotifierProviderを作成すると、別個のインスタンスになり、値を引き継げないと考えているのですが、どのようにすればよろしいでしょうか?
nskhei

2020/09/26 23:30

回答内のコードではChangeNotifierProvider.valueを使って、 元ページのモデルと同じインスタンスを供給するようにしています。
takumi123

2020/09/26 23:44

見落としていました! 申し訳ありません。 無事動作しました。大変感謝しております。 ありがとうございます!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問