下記のような2画面でテキスト文言を編集できるようなサンプルプログラムを記載しております。
TopScreen
・ListViewでテキストデータが並んで表示
・タップするとNectScreenへ遷移
NectScreen
・TopScreenで選択したテキストデータが編集可能
・キャンセルボタンを選択した際には編集前のデータを設定したい
実際に遷移前のページに正しい値が送れてるみたいなのですが、
キャンセルボタンを押しても遷移前のテキストデータが編集されてしまいます。
setStateがうまく効いてない気もするのですが、
原因などわかりますでしょうか。
処理は入ってるので書き方が違うのかもしれません。
下記を参考にしながら、似たような実装をしています。
[https://qiita.com/mamoru_takami/items/f53aebd97fb1140d122a]
Dart
1import 'package:flutter/material.dart'; 2 3void main() => runApp(MyApp()); 4 5class Todo { 6 final String title; 7 final String description; 8 Todo({ this.title, this.description}) 9 : assert(title != null), 10 assert(description != null); 11} 12 13class MyApp extends StatelessWidget { 14 15 Widget build(BuildContext context) { 16 return MaterialApp( 17 debugShowCheckedModeBanner: false, // Debug文言の削除 18 title: 'Navigation', 19 home: ListScreen2(title: 'List'), 20 ); 21 } 22} 23 24class Model { 25 String title; 26 String subTitle; 27 String key; 28 29 Model({ 30 this.title, 31 this.subTitle, 32 this.key, 33 }); 34} 35 36class ListScreen2 extends StatefulWidget { 37 ListScreen2({Key key, this.title}) : super(key: key); 38 39 final String title; 40 41 42 _ListScreenState2 createState() => _ListScreenState2(); 43} 44 45class _ListScreenState2 extends State<ListScreen2> { 46 List<Model> modelList; 47 48 49 // 起動時に初期化 50 void initState() { 51 super.initState(); 52 53 modelList = []; 54 List<String> titleList = ["Title A", "Title B", "Title C"]; 55 List<String> subTitleList = ["SubTitle A", "SubTitle B", "SubTitle C"]; 56 57 for (int i = 0; i < 3; i++) { 58 Model model = Model( 59 title: titleList[i], 60 subTitle: subTitleList[i], 61 key: i.toString(), 62 ); 63 modelList.add(model); 64 } 65 } 66 67 // リスト項目となる削除可能なウィジェットを作成 68 Widget buildItem(Model model, int index) { 69 return Dismissible( 70 key: Key('${model.key}'), // 項目が特定できるよう固有の文字列をキーとする 71 background: Container( 72 padding: EdgeInsets.only( 73 right: 48, 74 ), 75 alignment: AlignmentDirectional.centerEnd, 76 color: Colors.red, 77 child: Icon( 78 Icons.delete, 79 color: Colors.white, 80 ), 81 ), // スワイプしているアイテムの背景色 82 direction: DismissDirection.endToStart, 83 confirmDismiss: (direction) async { 84 // 削除するか確認する 85 return await showDialog( 86 context: context, 87 builder: (BuildContext context) { 88 return AlertDialog( 89 title: Text('確認ダイアログ'), 90 content: Text('本当に削除しますか?'), 91 actions: <Widget>[ 92 TextButton( 93 onPressed: () => Navigator.of(context).pop(false), 94 child: Text('CANCEL'), 95 ), 96 TextButton( 97 onPressed: () => Navigator.of(context).pop(true), 98 child: 99 Text('DELETE', style: TextStyle(color: Colors.red))), 100 ], 101 ); 102 }, 103 ); 104 }, 105 onDismissed: (direction) { 106 // 削除時の処理 107 setState(() { 108 modelList.remove(model); 109 }); 110 }, 111 // 各項目のレイアウト 112 child: Card( 113 child: ListTile( 114 tileColor: Theme.of(context).cardColor, 115 title: Text('${model.title}', 116 style: TextStyle( 117 fontWeight: FontWeight.bold, fontSize: 20, height: 1.2)), 118 subtitle: Text('${model.key} ${model.subTitle}'), 119 onTap: () async { 120 var result = await Navigator.push( 121 context, 122 MaterialPageRoute( 123 builder: (context) => NextScreen2(model: model))); 124 //print(result); 125 setState(() { 126 if (result != null) { 127 model = result; 128 print('set state ' + model.title); 129 } 130 }); 131 }, 132 ))); 133 } 134 135 136 Widget build(BuildContext context) { 137 return Scaffold( 138 appBar: AppBar( 139 title: Text(widget.title), 140 ), 141 body: Container( 142 child: ReorderableListView( 143 onReorder: (int oldIndex, int newIndex) { 144 if (newIndex > oldIndex) { 145 // 元々下にあった要素が上にずれるため一つ分後退させる 146 newIndex -= 1; 147 } 148 149 // 並び替え処理 150 Model model = modelList[oldIndex]; 151 setState(() { 152 modelList.removeAt(oldIndex); 153 modelList.insert(newIndex, model); 154 }); 155 }, 156 padding: EdgeInsets.only(top: 4), 157 children: modelList 158 .asMap() 159 .map((i, item) => MapEntry(i, buildItem(item, i))) 160 .values 161 .toList()) 162 //], 163 )); 164 } 165} 166 167/////////// 168 169class NextScreen2 extends StatefulWidget { 170 Model _model; 171 172 NextScreen2({Key key, Model model}) 173 : assert(model != null), 174 this._model = model, 175 super(key: key); 176 177 178 _NextScreenState2 createState() => _NextScreenState2(); 179} 180 181class _NextScreenState2 extends State<NextScreen2> { 182 // 起動時に初期化 183 Model _initModel; 184 185 void initState() { 186 super.initState(); 187 188 _initModel = Model( 189 title: widget._model.title, 190 subTitle: widget._model.subTitle, 191 key: widget._model.key, 192 ); 193 } 194 195 196 Widget build(BuildContext context) { 197 return WillPopScope( 198 onWillPop: () { 199 print('onWillPop'); 200 Navigator.of(context).pop(_initModel); 201 return Future.value(false); 202 }, 203 child: Scaffold( 204 appBar: AppBar( 205 title: Text('Edit'), 206 ), 207 body: Container( 208 padding: EdgeInsets.all(20), 209 child: Column( 210 mainAxisAlignment: MainAxisAlignment.start, 211 children: <Widget>[ 212 // タイトル 213 TextField( 214 controller: TextEditingController() 215 ..text = widget._model.title, 216 decoration: InputDecoration( 217 hintText: 'タイトル', 218 hintStyle: TextStyle( 219 color: Colors.black26, 220 ), 221 ), 222 onChanged: (text) { 223 widget._model.title = text; 224 }, 225 ), 226 227 // 登録ボタン 228 Container( 229 //padding: EdgeInsets.all(_PADDING_SIZE), 230 padding: EdgeInsets.fromLTRB(0, 10, 0, 10), 231 width: double.infinity, // 横幅いっぱいに広げる 232 height: 60, 233 child: ElevatedButton( 234 child: Text('確定'), 235 onPressed: () { 236 // TODO: 新規登録 237 // 前の画面に戻る 238 print('確定'); 239 if (Navigator.of(context).canPop()) { 240 Navigator.of(context).pop(widget._model); 241 } 242 }, 243 ), 244 ), 245 246 // キャンセルボタン 247 Container( 248 //padding: EdgeInsets.all(_PADDING_SIZE), 249 padding: EdgeInsets.fromLTRB(0, 10, 0, 10), 250 width: double.infinity, // 横幅いっぱいに広げる 251 height: 60, 252 child: ElevatedButton( 253 child: Text('キャンセル'), 254 onPressed: () { 255 print('キャンセル'); 256 // 前の画面に戻る 257 widget._model = _initModel; 258 if (Navigator.of(context).canPop()) { 259 Navigator.of(context).pop(null); 260 } 261 }, 262 style: ElevatedButton.styleFrom( 263 primary: Colors.grey[200], 264 onPrimary: Colors.black45, 265 ), 266 ), 267 ), 268 ], 269 ), 270 ), 271 )); 272 } 273} 274
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/26 02:37
2021/05/26 04:41
2021/05/26 04:57
2021/05/26 08:22 編集
2021/05/26 08:37