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

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

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

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

Q&A

解決済

1回答

2382閲覧

Flutterの再描画について

art_porokyu

総合スコア44

Flutter

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

0グッド

0クリップ

投稿2019/10/09 12:56

#flutterの再描画につい質問です。

イメージ説明説明](f21d958032a22478435fe15702a92348.jpeg)

##目的
右の数字のボタンを押すと、左にあるTextFormFieldに数字の値を反映させたいと考えております。

##コード

input.dart

1import 'package:flutter/material.dart'; 2import 'package:callsystem/home/home_view.dart'; 3import 'package:flutter/rendering.dart'; 4 5class InputPeoples extends StatefulWidget { 6 @override 7 _InputPeoplesState createState() => _InputPeoplesState(); 8} 9 10 11class _InputPeoplesState extends State<InputPeoples> { 12 13 // List<String> numList = ['1','2','3','4','5','6','7','8','9','0']; 14 String _initialValue; 15 16 void inputNum(String number) { 17 setState(() { 18 _initialValue = number; 19 }); 20 } 21 22 static _InputPeoplesState of(BuildContext context) { 23 return context.ancestorStateOfType(TypeMatcher<_InputPeoplesState>()); 24 } 25 26 @override 27 Widget build(BuildContext context) { 28 return Scaffold( 29 body: Column( 30 children: <Widget>[ 31 SafeArea( 32 child: _titleHeader(), 33 ), 34 SizedBox( 35 height: 50.0, 36 ), 37 Row( 38 mainAxisAlignment: MainAxisAlignment.spaceAround, 39 children: <Widget>[ 40 new InputFeild(), 41 Column( 42 children: <Widget>[ 43 Container( 44 margin: EdgeInsets.only(bottom: 30.0), 45 width: 450, 46 child: Row( 47 mainAxisAlignment: MainAxisAlignment.spaceBetween, 48 children: <Widget>[ 49 _buttonNumber(number: '1'), // 数字ボタンのwidget 50 _buttonNumber(number: '2'), 51 _buttonNumber(number: '3'), 52 ], 53 ), 54 ), 55 Container( 56 margin: EdgeInsets.only(bottom: 30.0), 57 width: 450, 58 child: Row( 59 mainAxisAlignment: MainAxisAlignment.spaceBetween, 60 children: <Widget>[ 61 _buttonNumber(number: '4'), 62 _buttonNumber(number: '5'), 63 _buttonNumber(number: '6'), 64 ], 65 ), 66 ), 67 Container( 68 margin: EdgeInsets.only(bottom: 30.0), 69 width: 450, 70 child: Row( 71 mainAxisAlignment: MainAxisAlignment.spaceBetween, 72 children: <Widget>[ 73 _buttonNumber(number: '7'), 74 _buttonNumber(number: '8'), 75 _buttonNumber(number: '9'), 76 ], 77 ), 78 ), 79 ], 80 ) 81 ], 82 ) 83 ], 84 ) 85 ); 86 } 87 88 Widget _buttonNumber({String number}){ 89 return Stack( 90 children: <Widget>[ 91 Container( 92 width: 130.0, 93 height: 140.0, 94 ), 95 Positioned( 96 top: 10, 97 width: 130.0, 98 height: 130.0, 99 child: Container( 100 decoration: BoxDecoration( 101 color: Color(0xFF696969), 102 borderRadius: BorderRadius.all(Radius.circular(10.0)), 103 ), 104 ), 105 ), 106 Container( 107 width: 130.0, 108 height: 130.0, 109 decoration: BoxDecoration( 110 border: Border.all(color: Color(0xFF696969)), 111 borderRadius: BorderRadius.circular(10), 112 ), 113 child: FlatButton( 114 color: Color(0xFFF5F5F5), 115 child: Text( 116 '$number', 117 style: TextStyle( 118 fontSize: 40.0 119 ), 120 ), 121 shape: RoundedRectangleBorder( 122 borderRadius: BorderRadius.all(Radius.circular(10.0)), 123 ), 124 onPressed: (){ 125 inputNum(number); 126 }, 127 ) 128 ), 129 ], 130 ); 131 } 132 133 Widget _titleHeader(){ 134 return Column( 135 children: <Widget>[ 136 Row( 137 mainAxisAlignment: MainAxisAlignment.spaceBetween, 138 children: <Widget>[ 139 Container( 140 margin: EdgeInsets.only(left: 50.0), 141 child: Text( 142 '人数を入力してください', 143 style: TextStyle( 144 fontSize: 32.0, 145 ) 146 ), 147 ), 148 Container( 149 margin: EdgeInsets.only(right: 50.0), 150 child: FlatButton( 151 child: Image.asset( 152 'images/icon/home.png', 153 width: 60.0, 154 height: 60.0, 155 ), 156 onPressed: (){ 157 Navigator.pop( 158 context, 159 MaterialPageRoute(builder: (context) => HomeView()), 160 ); 161 }, 162 ) 163 ), 164 ] 165 ), 166 Row( 167 mainAxisAlignment: MainAxisAlignment.center, 168 children: <Widget>[ 169 Container( 170 width: 1300.0, 171 child: Divider( 172 color: Colors.grey[800] 173 ), 174 ) 175 ], 176 ), 177 ], 178 ); 179 } 180} 181 182 class InputFeild extends StatelessWidget{ 183 @override 184 Widget build(BuildContext context){ 185 String _initialValue = _InputPeoplesState.of(context)._initialValue; 186 print(_initialValue); 187 return Container( 188 width: 350.0, 189 decoration: BoxDecoration( 190 borderRadius:BorderRadius.all(Radius.circular(20.0)), 191 border: Border( 192 top: BorderSide(width: 6.0, color: Color(0xFF696969)), 193 left: BorderSide(width: 6.0, color: Color(0xFF696969)), 194 right: BorderSide(width: 6.0, color: Color(0xFF696969)), 195 bottom: BorderSide(width: 6.0, color: Color(0xFF696969)), 196 ) 197 ), 198 child: TextFormField( 199 initialValue: _initialValue, 200 style: TextStyle( 201 fontSize: 60.0, 202 color: Color(0xFF696969) 203 ), 204 decoration: InputDecoration( 205 contentPadding: EdgeInsets.symmetric(vertical: 50.0, horizontal: 20.0), 206 border: InputBorder.none, 207 ), 208 ), 209 ); 210 } 211 }

##やっていること
数字ボタンを押すとinputNumメソッドが走り、数字の値が_initialValueに格納されます。
_initialValueの値をTextFormFieldのinitialValueプロパティに当てています。

printで見ると変数に値は入っているのですが、上手く再描画されません。

外部からTextFormFieldの入力値を変える場合はどのようにすればいいでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

TextFormFieldに値を渡す方法をinitialValueではなくcontrollerにするとうまく更新されました。

InputFeild のコードを貼っておきます。

class InputFeild extends StatefulWidget { @override _InputFeildState createState() => _InputFeildState(); } class _InputFeildState extends State<InputFeild> { final _controller = TextEditingController(); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { String _initialValue = _InputPeoplesState.of(context)._initialValue; print(_initialValue); _controller.text = _initialValue; return Container( width: 350.0, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(20.0)), border: Border( top: BorderSide(width: 6.0, color: Color(0xFF696969)), left: BorderSide(width: 6.0, color: Color(0xFF696969)), right: BorderSide(width: 6.0, color: Color(0xFF696969)), bottom: BorderSide(width: 6.0, color: Color(0xFF696969)), )), child: TextFormField( controller: _controller, style: TextStyle(fontSize: 60.0, color: Color(0xFF696969)), decoration: InputDecoration( contentPadding: EdgeInsets.symmetric(vertical: 50.0, horizontal: 20.0), border: InputBorder.none, ), ), ); } }

TextFormFieldinitialValueを使った場合、初期化時に内部でcontrollerを生成してしまい、リビルド時に内部のcontrollerの値を更新できないので、値が変更されないようでした。
なので自前でcontrollerを生成して、ビルド時に_controller.text = _initialValue;で値を渡してあげればよいようです。

controllerを保持して、disposeするために、InputFeildStatelessWidgetからStatefulWidgetに変えています。


補足

公式リファレンスにもそれっぽいことが書いてありました

If a controller is not specified, initialValue can be used to give the automatically generated controller an initial value.

コードを読むと、 TextFormFieldStatefulWidgetになっていて、initStatecontroller生成しているようです。

投稿2019/10/09 21:24

編集2019/10/09 21:59
popobot

総合スコア6586

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

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

art_porokyu

2019/10/10 01:22

ご丁寧にありがとうございます! >TextFormFieldはinitialValueを使った場合、初期化時に内部でcontrollerを生成してしまい、リビルド時に内部のcontrollerの値を更新できないので、値が変更されないようでした。 なるほど。 それでビルド時の値が変わらなかったのですね。 余談になるかもしれないのですが、superやofなどはどのような役割をしているのでしょうか?
popobot

2019/10/10 02:32

superは継承元の親クラスのメソッドを呼び出すために利用するDartの機能です。dispose()は親クラスであるStatefulWidgetにも定義されているメソッドなので、overrideした場合 super.dispose() を呼ぶ必要があります。 ofはFlutterで最も近い親Widgetを取得するメソッド名によく使われます。親Widgetのテーマを取得する場合 Theme.of()などを使います。 コード上のofは art_porokyuさん が定義しているメソッドのようですが、InputFeildからInputPeoplesStateを取得するのに利用されています。
art_porokyu

2019/10/10 03:22

なるほど。 superはdartの機能なんですね。 ofも使い方が分かりました! ご丁寧にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問