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

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

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

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

Dart

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

Q&A

解決済

1回答

1775閲覧

スクロールバーにおける、初期値の代入方法

soichiro1210

総合スコア6

Flutter

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

Dart

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

0グッド

0クリップ

投稿2023/10/05 01:36

実現したいこと

現在、Flutterを使って、グラフ描画を行うようなWindowsアプリを開発しています。

前提

その中で、グラフにスクロールバーを追加するために、SingleChildScrollViewを使用しています。

発生している問題・エラーメッセージ

その際に、スクロールの位置情報初期値がないというエラーが出る。
これを解決する方法を教えて頂きたいです。

ScrollController not attached to any scroll views. 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 155 pos 12: '_positions.isNotEmpty'

該当のソースコード

dart

1class kewSfCartesianChart extends StatelessWidget { 2 kewSfCartesianChart(this._target); 3 4 final int _target; 5 late ZoomMode _zoomMode; 6 late String _title; 7 late String _unit; 8 ScrollController _xAxisScrollController = ScrollController(); 9 ScrollController _yAxisScrollController = ScrollController(); 10 11 12 Widget build(BuildContext context) { 13 _zoomMode = ZoomMode.xy; 14 _xAxisScrollController = ScrollController(initialScrollOffset: 5); 15 _yAxisScrollController = ScrollController(initialScrollOffset: 5); 16 return Consumer<GraphDataStore>( 17 builder: (context, graphStore, _) { 18 List<MeasData> displayData1; 19 List<MeasData> displayData2; 20 List<MeasData> displayData3; 21 if (_target == VOLT) { 22 _title = "電圧"; 23 _unit = "(V)"; 24 displayData1 = graphStore.displayDataVolt1; 25 displayData2 = graphStore.displayDataVolt2; 26 displayData3 = graphStore.displayDataVolt3; 27 print("グラフ更新"); 28 } else { 29 _title = "電流"; 30 _unit = "(A)"; 31 displayData1 = graphStore.displayDataCurrent1; 32 displayData2 = graphStore.displayDataCurrent2; 33 displayData3 = graphStore.displayDataCurrent3; 34 } 35 return SingleChildScrollView( 36 scrollDirection: Axis.horizontal, 37 controller: _xAxisScrollController, 38 child: SingleChildScrollView( 39 scrollDirection: Axis.vertical, 40 controller: _yAxisScrollController, 41 child: Column( 42 children: [ 43 Slider( 44 value: _xAxisScrollController.position.pixels, 45 min: _xAxisScrollController.position.minScrollExtent, 46 max: _xAxisScrollController.position.maxScrollExtent, 47 onChanged: (value){ 48 _xAxisScrollController.jumpTo(value); 49 }, 50 ), 51 Slider( 52 value: _yAxisScrollController.position.pixels, 53 min: _yAxisScrollController.position.minScrollExtent, 54 max: _yAxisScrollController.position.maxScrollExtent, 55 onChanged: (value){ 56 _yAxisScrollController.jumpTo(value); 57 }, 58 ), 59 60 SfCartesianChart( 61 //key: ObjectKey(displayData1), 62 /* 63 onChartTouchInteractionDown: (_) { 64 print("Down"); 65 }, 66 onChartTouchInteractionUp: (_) { 67 print("Up"); 68 },*/ 69 enableAxisAnimation: true, 70 plotAreaBorderWidth: 0, 71 title: ChartTitle(text: '$_title$_unit'), 72 legend: const Legend(isVisible: true), 73 tooltipBehavior: TooltipBehavior(enable: true), 74 series: <ChartSeries>[ 75 LineSeries<MeasData, String>( 76 dataSource: displayData1, 77 xValueMapper: (MeasData data, _) => 78 data.dateYmd + ("\n") + data.dateHms, 79 yValueMapper: (MeasData data, _) => data.data, 80 dataLabelSettings: 81 const DataLabelSettings(isVisible: false), 82 name: '${_title}1', 83 enableTooltip: true, 84 ), 85 LineSeries<MeasData, String>( 86 dataSource: displayData2, 87 xValueMapper: (MeasData data, _) => 88 data.dateYmd + ("\n") + data.dateHms, 89 yValueMapper: (MeasData data, _) => data.data, 90 dataLabelSettings: 91 const DataLabelSettings(isVisible: false), 92 name: '${_title}2', 93 enableTooltip: true, 94 ), 95 LineSeries<MeasData, String>( 96 dataSource: displayData3, 97 xValueMapper: (MeasData data, _) => 98 data.dateYmd + ("\n") + data.dateHms, 99 yValueMapper: (MeasData data, _) => data.data, 100 dataLabelSettings: 101 const DataLabelSettings(isVisible: false), 102 name: '${_title}3', 103 enableTooltip: true, 104 ), 105 ], 106 primaryXAxis: CategoryAxis( 107 maximumLabels: displayData1.length, 108 autoScrollingDelta: 30, 109 autoScrollingMode: AutoScrollingMode.start, 110 ), 111 primaryYAxis: NumericAxis( 112 minimum: 1.0, 113 ), 114 zoomPanBehavior: ZoomPanBehavior( 115 enablePanning: true, 116 zoomMode: _zoomMode, 117 enablePinching: true, 118 enableMouseWheelZooming: true, 119 ), 120 ), 121 ], 122 )), 123 ); 124 }, 125 ); 126 } 127} 128

試したこと

元のソースに14,15行目を追加した。

dart

1 _xAxisScrollController = ScrollController(initialScrollOffset: 5); 2 _yAxisScrollController = ScrollController(initialScrollOffset: 5);

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

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

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

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

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

guest

回答1

0

ベストアンサー

ScrollControllerのpositionはSingleChildScrollViewに関連付けられて初めて使用できます。
buildメソッド内ではその関連付けはまだされてません。
そのためアクセスしようとするとエラーが出ます。

以下は、なんとなく動く実装です。
ウィジェットはStatefulWidget派生にしています。

  • _handleAはスクロールがされた場合に呼び出される処理で、ここでスクロール位置を取り出します。
    min,max位置も取り出してますが、Sliderの初期値のmin/maxを指定するためのデータを取り出すこともしたかったので、ここに収めて共通化してます。
  • initState内では2種類のことをしてます。
    一つが、スクロールした場合に_handleAの関数を呼び出すための設定。
    もう一つが、min,maxが確定した場合にそれをスライダーに設定するための処理。
    前者はスクロールしないと呼び出されないので、min/maxの値を取り出すため、ウィジェットの実体が作成された後ぐらいに_handleAを呼び出すようにFuture.delayedを入れてます。

dart

1class _HogeState extends State<Hoge> { 2 late final ScrollController _controller; 3 double _position = 0; 4 double _max = 0; 5 double _min = 0; 6 void _handleA() { 7 setState(() { 8 _position = _controller.offset; 9 _max = _controller.position.maxScrollExtent; 10 _min = _controller.position.minScrollExtent; 11 }); 12 } 13 14 15 void initState() { 16 _controller = ScrollController(); 17 _controller.addListener(_handleA); 18 Future.delayed(const Duration(milliseconds: 500)) 19 .then((value) => _handleA()); 20 super.initState(); 21 } 22 23 24 void dispose() { 25 _controller.removeListener(_handleA); 26 super.dispose(); 27 } 28 29 30 Widget build(BuildContext context) { 31 return Scaffold( 32 body: SingleChildScrollView( 33 controller: _controller, 34 child: Column(children: [ 35 Slider( 36 value: _position, 37 max: _max, 38 min: _min, 39 onChanged: (value) { 40 setState(() { 41 _controller.jumpTo(value); 42 }); 43 }, 44 ),

投稿2023/10/05 08:58

ta.fu

総合スコア1742

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

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

soichiro1210

2023/10/06 06:09

詳しい解説ありがとうございます。 現在グラフをStatelessWidgetとProviderを組み合わせて作っています。スクロールバーの問題以外にもStatefulWidgetの方が便利だなと感じる部分が多々あるため、作り直したら改めてコメントします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問