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

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

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

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

Q&A

解決済

1回答

1137閲覧

flutterにて、リストからの画面遷移で1対1対応がうまくいかない

flutter_labo

総合スコア110

Flutter

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

1グッド

0クリップ

投稿2020/02/26 05:51

![イメージ説明

このリストで**[国語]を押した時、次ページでは[現代文][古文][漢文]
また、
[数学]を押した時、次ページでは[三角関数][因数分解][数列]**。
のように表示したいと考えております。

ExpansionTileを利用したいと考えており、少し複雑になってしまいました…。

Flutter

1import 'package:flutter/material.dart'; 2 3// B. main関数 4void main() { 5 // C. runApp関数 6 runApp(MyApp()); 7} 8 9// D. StatelessWidgetを継承したクラス 10class MyApp extends StatelessWidget { 11 @override 12 Widget build(BuildContext context) { 13 return MaterialApp( 14 title: 'Flutter Demo', 15 // N-1. Theme 16 theme: ThemeData( 17 primarySwatch: Colors.blue, 18 ), 19 home: MyHomePage(title: 'StudySummary'), 20 ); 21 } 22} 23 24// E. StatefulWidgetを継承したクラス 25class MyHomePage extends StatefulWidget { 26 // コンストラクター 27 MyHomePage({Key key, this.title}) : super(key: key); 28 29 // 受け取った文字列の入れ物 30 final String title; 31 32 @override 33 State<StatefulWidget> createState() => _MyHomePageState(); 34} 35 36// F. Stateを継承したクラス 37class _MyHomePageState extends State<MyHomePage> { 38 // G. 状態の保持と更新 39 var listItem = ["国語","数学","英語","化学","物理","その他"]; 40 // H. _MyHomePageStateのbuildメソッド 41 @override 42 Widget build(BuildContext context) { 43 // K. ページはScaffoldで組む 44 return Scaffold( 45 // L. AppBar 46 appBar: AppBar( 47 title: Text(widget.title, 48 style: TextStyle( 49 fontStyle: FontStyle.italic, 50 fontWeight:FontWeight.bold, 51 fontSize: 18, 52 ), 53 ), 54 ), 55 // M. bodyでページの中身をレイアウト 56 body: ListView.builder( 57 itemBuilder: (BuildContext context, int index) { 58 return Container( 59 decoration: BoxDecoration( 60 border: Border( 61 bottom: BorderSide(color: Colors.black38), 62 ), 63 ), 64 child: Padding( 65 padding: const EdgeInsets.only(top:8.5,left: 10.0), 66 child: ListTile( 67 leading: const Icon(Icons.book), 68 title: Text(listItem[index], 69 style: TextStyle( 70 fontWeight: FontWeight.bold, 71 fontSize: 20, 72 ), 73 ), 74 subtitle: Text('subject'), 75 onTap: () {Navigator.push( 76 context, 77 MaterialPageRoute(builder: (context) => SecondRoute(title: listItem[index],)), 78 );}, 79 ), 80 )); 81 },itemCount: listItem.length,), 82 ); 83 } 84} 85//2ページ目 86class SecondRoute extends StatefulWidget { 87 SecondRoute({Key key,this.title,}) : super(key: key); 88 // 受け取った文字列の入れ物 89 final String title; 90 91 @override 92 _SecondRouteState createState() => _SecondRouteState(); 93} 94 95class _SecondRouteState extends State<SecondRoute> { 96 97 @override 98 Widget build(BuildContext context) { 99 return MaterialApp( 100 home: Scaffold( 101 appBar: AppBar( 102 title:Text( 103 widget.title, 104 style: TextStyle( 105 fontWeight: FontWeight.bold, 106 fontStyle: FontStyle.italic, 107 fontSize: 18, 108 ), 109 ), 110 ), 111 body: ListView.builder( 112 itemBuilder: (BuildContext context, int index) { 113 return Container(child: EntryItem(data[index]), 114 decoration: BoxDecoration( 115 border: Border( 116 bottom: BorderSide(color: Colors.black38), 117 ), 118 ), 119 120 ); 121 }, 122 itemCount: data.length, 123 ), 124 ), 125 ); 126 } 127} 128 129class Entry { 130 Entry(this.title, [this.children = const <Entry>[]]); 131 final String title; 132 final List<Entry> children; 133} 134 135final List<Entry> data = <Entry>[ 136 Entry( 137 '現代文', 138 <Entry>[ 139 Entry('現代文の動画1'), 140 Entry('現代文の動画2'), 141 Entry('現代文の動画3'), 142 Entry('現代文の動画4'), 143 ] 144 ), 145 Entry( 146 '古文', 147 <Entry>[ 148 Entry('古文の動画1'), 149 Entry('古文の動画2'), 150 Entry('古文の動画3'), 151 Entry('古文の動画4'), 152 ] 153 ), 154 Entry( 155 '漢文', 156 <Entry>[ 157 Entry('漢文の動画1'), 158 Entry('漢文の動画2'), 159 Entry('漢文の動画3'), 160 Entry('漢文の動画4'), 161 ] 162 ), 163 Entry( 164 '文法', 165 <Entry>[ 166 Entry('文法の動画1'), 167 Entry('文法の動画2'), 168 Entry('文法の動画3'), 169 Entry('文法の動画4'), 170 ] 171 ), 172]; 173 174 175final List<Entry> data2 = <Entry>[ 176 Entry( 177 '三角関数', 178 <Entry>[ 179 Entry('三角関数の動画1'), 180 Entry('三角関数の動画2'), 181 Entry('三角関数の動画3'), 182 Entry('三角関数動画4'), 183 ] 184 ), 185 Entry( 186 '数列', 187 <Entry>[ 188 Entry('数列の動画1'), 189 Entry('数列の動画2'), 190 Entry('数列の動画3'), 191 Entry('数列の動画4'), 192 ] 193 ), 194 Entry( 195 '因数分解', 196 <Entry>[ 197 Entry('因数分解の動画1'), 198 Entry('因数分解の動画2'), 199 Entry('因数分解の動画3'), 200 Entry('因数分解の動画4'), 201 ] 202 ), 203 Entry( 204 '確率', 205 <Entry>[ 206 Entry('確率の動画1'), 207 Entry('確率の動画2'), 208 Entry('確率の動画3'), 209 Entry('確率の動画4'), 210 ] 211 ), 212]; 213 214 215final List<Entry> data3 = <Entry>[ 216 Entry( 217 '英単語', 218 <Entry>[ 219 Entry('英単語の動画1'), 220 Entry('英単語の動画2'), 221 Entry('英単語の動画3'), 222 Entry('英単語の動画4'), 223 ] 224 ), 225 Entry( 226 '英文法', 227 <Entry>[ 228 Entry('英文法の動画1'), 229 Entry('英文法の動画2'), 230 Entry('英文法の動画3'), 231 Entry('英文法の動画4'), 232 ] 233 ), 234 Entry( 235 '長文対策', 236 <Entry>[ 237 Entry('長文対策の動画1'), 238 Entry('長文対策の動画2'), 239 Entry('長文対策の動画3'), 240 Entry('長文対策の動画4'), 241 ] 242 ), 243 Entry( 244 'リスニング', 245 <Entry>[ 246 Entry('リスニングの動画1'), 247 Entry('リスニングの動画2'), 248 Entry('リスニングの動画3'), 249 Entry('リスニングの動画4'), 250 ] 251 ), 252]; 253 254//final List<Entry> data4 = <Entry>[data,data2,data3]; 255 256 257// with an ExpansionTile. 258class EntryItem extends StatelessWidget { 259 const EntryItem(this.entry); 260 final Entry entry; 261//expansionリストの一番下にいる子供達 262 263 Widget _buildTiles(BuildContext context, Entry root) { 264 if (root.children.isEmpty) 265 return Padding( 266 padding: const EdgeInsets.only(left: 18.0), 267 child: ListTile( 268 269 //leading: const Icon(Icons.vpn_key), 270 leading: const Icon(Icons.phone_android), 271 title: Text( 272 root.title, 273 style: TextStyle( 274 fontWeight: FontWeight.bold, 275 fontSize: 18, 276 ), 277 ), 278 subtitle: Text("movie"), 279 onTap: () {}), 280 ); 281 //expansionリストの下から2番目にいる子供達 282 return Padding( 283 padding: const EdgeInsets.only(top: 8.0, left: 10.0), 284 child: ExpansionTile( 285 leading: const Icon(Icons.book), 286 key: PageStorageKey<Entry>(root), 287 title: Text( 288 root.title, 289 style: TextStyle( 290 fontWeight: FontWeight.bold, 291 fontSize: 18, 292 ), 293 ), 294 subtitle: Text("unit"), 295 children: 296 root.children.map((entry) => _buildTiles(context, entry)).toList(), 297 ), 298 ); 299 } 300 301 @override 302 Widget build(BuildContext context) { 303 return _buildTiles(context, entry); 304 } 305}

やってみたこと

dataの定義の仕方でなんとなく解決できそうだと考えて色々考えてみたのですが、うまくいかなかったです。ご教授よろしくお願いします

popobot👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

Entryというクラスを「国語」や「数学」などのトップカテゴリでも使用すればどうでしょうか
これなら、各データが1つになって関連性が明確だと思います。
もしデータを1ページ目と2ページ目で分けたいなら、お互いの関係がわかるようなIDを双方のデータに渡せばできると思います。

final List<Entry> data = [ Entry('国語', <Entry>[ Entry('現代文', <Entry>[ Entry('現代文の動画1'), Entry('現代文の動画2'), Entry('現代文の動画3'), Entry('現代文の動画4'), ]),  (以下省略) ]), ];

動作確認に使った全体コードも貼っておいます(なんかこのコード、トップページに戻れないですね...なんでだろ)

import 'package:flutter/material.dart'; // B. main関数 void main() { // C. runApp関数 runApp(MyApp()); } // D. StatelessWidgetを継承したクラス class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', // N-1. Theme theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'StudySummary'), ); } } // E. StatefulWidgetを継承したクラス class MyHomePage extends StatefulWidget { // コンストラクター MyHomePage({Key key, this.title}) : super(key: key); // 受け取った文字列の入れ物 final String title; @override State<StatefulWidget> createState() => _MyHomePageState(); } // F. Stateを継承したクラス class _MyHomePageState extends State<MyHomePage> { // H. _MyHomePageStateのbuildメソッド @override Widget build(BuildContext context) { // K. ページはScaffoldで組む return Scaffold( // L. AppBar appBar: AppBar( title: Text( widget.title, style: TextStyle( fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), // M. bodyでページの中身をレイアウト body: ListView.builder( itemBuilder: (BuildContext context, int index) { return Container( decoration: BoxDecoration( border: Border( bottom: BorderSide(color: Colors.black38), ), ), child: Padding( padding: const EdgeInsets.only(top: 8.5, left: 10.0), child: ListTile( leading: const Icon(Icons.book), title: Text( data[index].title, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, ), ), subtitle: Text('subject'), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => SecondRoute(entry: data[index])), ); }, ), )); }, itemCount: data.length, ), ); } } //2ページ目 class SecondRoute extends StatefulWidget { SecondRoute({Key key, this.entry}) : super(key: key); // 受け取った文字列の入れ物 final Entry entry; @override _SecondRouteState createState() => _SecondRouteState(); } class _SecondRouteState extends State<SecondRoute> { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text( widget.entry.title, style: TextStyle( fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, fontSize: 18, ), ), ), body: ListView.builder( itemBuilder: (BuildContext context, int index) { return Container( child: EntryItem(widget.entry.children[index]), decoration: BoxDecoration( border: Border( bottom: BorderSide(color: Colors.black38), ), ), ); }, itemCount: widget.entry.children.length, ), ), ); } } class Entry { Entry(this.title, [this.children = const <Entry>[]]); final String title; final List<Entry> children; } final List<Entry> data = [ Entry('国語', <Entry>[ Entry('現代文', <Entry>[ Entry('現代文の動画1'), Entry('現代文の動画2'), Entry('現代文の動画3'), Entry('現代文の動画4'), ]), Entry('古文', <Entry>[ Entry('古文の動画1'), Entry('古文の動画2'), Entry('古文の動画3'), Entry('古文の動画4'), ]), Entry('漢文', <Entry>[ Entry('漢文の動画1'), Entry('漢文の動画2'), Entry('漢文の動画3'), Entry('漢文の動画4'), ]), Entry('文法', <Entry>[ Entry('文法の動画1'), Entry('文法の動画2'), Entry('文法の動画3'), Entry('文法の動画4'), ]), ]), Entry('数学', <Entry>[ Entry('三角関数', <Entry>[ Entry('三角関数の動画1'), Entry('三角関数の動画2'), Entry('三角関数の動画3'), Entry('三角関数動画4'), ]), Entry('数列', <Entry>[ Entry('数列の動画1'), Entry('数列の動画2'), Entry('数列の動画3'), Entry('数列の動画4'), ]), Entry('因数分解', <Entry>[ Entry('因数分解の動画1'), Entry('因数分解の動画2'), Entry('因数分解の動画3'), Entry('因数分解の動画4'), ]), Entry('確率', <Entry>[ Entry('確率の動画1'), Entry('確率の動画2'), Entry('確率の動画3'), Entry('確率の動画4'), ]), ]), Entry('英語', <Entry>[ Entry('英単語', <Entry>[ Entry('英単語の動画1'), Entry('英単語の動画2'), Entry('英単語の動画3'), Entry('英単語の動画4'), ]), Entry('英文法', <Entry>[ Entry('英文法の動画1'), Entry('英文法の動画2'), Entry('英文法の動画3'), Entry('英文法の動画4'), ]), Entry('長文対策', <Entry>[ Entry('長文対策の動画1'), Entry('長文対策の動画2'), Entry('長文対策の動画3'), Entry('長文対策の動画4'), ]), Entry('リスニング', <Entry>[ Entry('リスニングの動画1'), Entry('リスニングの動画2'), Entry('リスニングの動画3'), Entry('リスニングの動画4'), ]), ]), ]; //final List<Entry> data4 = <Entry>[data,data2,data3]; // with an ExpansionTile. class EntryItem extends StatelessWidget { const EntryItem(this.entry); final Entry entry; //expansionリストの一番下にいる子供達 Widget _buildTiles(BuildContext context, Entry root) { if (root.children.isEmpty) return Padding( padding: const EdgeInsets.only(left: 18.0), child: ListTile( //leading: const Icon(Icons.vpn_key), leading: const Icon(Icons.phone_android), title: Text( root.title, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), subtitle: Text("movie"), onTap: () {}), ); //expansionリストの下から2番目にいる子供達 return Padding( padding: const EdgeInsets.only(top: 8.0, left: 10.0), child: ExpansionTile( leading: const Icon(Icons.book), key: PageStorageKey<Entry>(root), title: Text( root.title, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), subtitle: Text("unit"), children: root.children.map((entry) => _buildTiles(context, entry)).toList(), ), ); } @override Widget build(BuildContext context) { return _buildTiles(context, entry); } }

投稿2020/02/26 11:13

編集2020/02/26 11:26
popobot

総合スコア6586

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

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

flutter_labo

2020/02/26 12:13

すごく分かりやすいアドバイスありがとうございます!! 僕も早くpopobotさんみたいに、知識豊富なカッコいいプログラマーになりたいです。 本当にありがとうございました!  戻るボタンが出ないの不思議ですよね。。。なんとか出してみます笑
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問