DB取得後、setStateで切り替えるイメージではいるのですが、どのようにするのでしょうか?
FutureBuilder
を使って、データ取得前と取得後でウィジェットを出し分けるというのはどうでしょうか?
少し抽象的なコードですが、大体こんな感じの雰囲気になるかと思います。
dart
1const sampleData = [
2 {
3 'name': '山本太郎',
4 'img': '../assets/images/sample.jpg',
5 'comment': 'ここに一言入ります',
6 'age': '22' + '歳',
7 },
8 {
9 'name': '山本花子',
10 'img': '../assets/images/sample.jpg',
11 'comment': 'ここに一言入ります',
12 'age': '22' + '歳',
13 },
14 {
15 'name': '田中花子',
16 'img': '../assets/images/sample.jpg',
17 'comment': 'ここに一言入ります',
18 'age': '22' + '歳',
19 },
20];
21
22class StuffListSection extends StatefulWidget {
23 @override
24 _StuffListSectionState createState() => _StuffListSectionState();
25}
26
27class _StuffListSectionState extends State<StuffListSection> {
28
29 Future<List<Map<String, dynamic>>> staffs; // 取得したデータを保持するための変数
30
31 @override
32 void initState() {
33 super.initState();
34 stuffs = _loadStaffData(); // データ取得開始
35 }
36
37 Future<List<Map<String, dynamic>>> _loadStaffData() async {
38 return sampleData; // 実際はDBからデータを取得して返す
39 }
40
41 @override
42 Widget build(BuildContext context) {
43 return Column(
44 children: [
45 const Text('スタッフ一覧'),
46 Container(
47 height: 200,
48 // FutureBuilderを使って、データ取得前と取得後でウィジェットを出し分ける。
49 child: FutureBuilder<List<Map<String, dynamic>>>(
50 future: staffs,
51 builder: (context, snapshot) {
52 // データが取得できるまではプレースホルダーを表示
53 if (!snapshot.hasData) {
54 return StaffListPlaceHolder();
55 }
56 // データ取得後に表示したいもの (取得したデータは`snapshot.data`に入る)
57 return ...
58 },
59 ),
60 ),
61 ],
62 );
63 }
64}
dart
1// データが取得できるまでのプレースホルダー。
2class StaffListPlaceHolder extends StatelessWidget {
3 @override
4 Widget build(BuildContext context) {
5 return ListView(
6 scrollDirection: Axis.horizontal,
7 children: List.generate(10, (_) {
8 return Card(
9 color: Colors.grey[300],
10 child: const SizedBox(width: 150),
11 );
12 }),
13 );
14 }
15}
※ 表示するスタッフの数はデータが取得できるまで分からないと考えて、ListView
全体をプレースホルダー化してます。
あとはこの辺のパッケージを使うと見た目も良い感じになるかもしれません。
追記
上記の回答は手元で考えてみたのをそのまま貼ったので、元のコードから離れすぎてて、あまり参考にならないかもしれません。
なるべく最小限の修正 + setStateだけで、それっぽいコード書いたので、こっち参考にしてください。
dart
1class ListViewHorizonCast extends StatefulWidget {
2 @override
3 _ListViewHorizonCastState createState() => _ListViewHorizonCastState();
4}
5
6class _ListViewHorizonCastState extends State<ListViewHorizonCast> {
7 List<Map<String, dynamic>> listItems;
8
9 @override
10 void didChangeDependencies() {
11 super.didChangeDependencies();
12 if (listItems == null) {
13 _loadData();
14 }
15 }
16
17 Future<void> _loadData() async {
18 // データ取得に1秒かかった想定
19 await Future.delayed(Duration(seconds: 1));
20 setState(() {
21 listItems = [
22 {
23 'name': '山本太郎',
24 'img': '../assets/images/sample.jpg',
25 'comment': 'ここに一言入ります',
26 'age': '22' + '歳',
27 },
28 {
29 'name': '山本花子',
30 'img': '../assets/images/sample.jpg',
31 'comment': 'ここに一言入ります',
32 'age': '22' + '歳',
33 },
34 {
35 'name': '田中花子',
36 'img': '../assets/images/sample.jpg',
37 'comment': 'ここに一言入ります',
38 'age': '22' + '歳',
39 },
40 ];
41 });
42 }
43
44 @override
45 Widget build(BuildContext context) {
46 return Container(
47 color: Colors.white,
48 margin: EdgeInsets.only(top: 10.0),
49 padding: EdgeInsets.symmetric(
50 horizontal: Settings().sidePadding(),
51 vertical: 20,
52 ),
53 child: Column(
54 children: <Widget>[
55 //タイトル
56 Container(
57 width: double.infinity,
58 margin: EdgeInsets.only(top: 0.0, bottom: 0.0),
59 height: 30,
60 child: Text(
61 'スタッフ一覧',
62 style: Settings.fontTitleStyle,
63 textAlign: TextAlign.left,
64 ),
65 ),
66 //カードリスト
67 Container(
68 height: 200,
69 padding: EdgeInsets.only(bottom: 15.0),
70 child: ListView.builder(
71 scrollDirection: Axis.horizontal,
72 itemCount: listItems?.length ?? 3,
73 itemBuilder: (context, index) {
74 //カード
75 return FlatButton(
76 child: SizedBox(
77 width: 150,
78 child: Card(
79 child: Stack(
80 fit: StackFit.expand,
81 children: <Widget>[
82 listItems == null
83 //グレーアウト
84 ? Container(color: Colors.grey[200])
85 //スタッフの写真
86 : Container(
87 child: Container(
88 decoration: BoxDecoration(
89 image: DecorationImage(
90 image: AssetImage(
91 '../assets/images/sample.jpg',
92 ),
93 fit: BoxFit.cover,
94 ),
95 ),
96 child: Container(
97 decoration: BoxDecoration(
98 gradient: LinearGradient(
99 begin: Alignment.topCenter,
100 end: Alignment.bottomCenter,
101 stops: [0.5, 0.75, 0.95],
102 colors: [
103 Colors.black12,
104 Colors.black54,
105 Colors.black87,
106 ],
107 ),
108 ),
109 ),
110 ),
111 ),
112 //スタッフの名前
113 Positioned(
114 bottom: 25.0,
115 left: 5.0,
116 child: Text(
117 listItems != null ? listItems[index]['name'] : '',
118 style: TextStyle(
119 color: Colors.white,
120 fontSize: 14,
121 fontWeight: FontWeight.bold,
122 ),
123 ),
124 ),
125 //スタッフの一言
126 Positioned(
127 bottom: 8.0,
128 left: 5.0,
129 child: Text(
130 listItems != null
131 ? listItems[index]['comment']
132 : '',
133 style: TextStyle(
134 color: Colors.white70,
135 fontSize: 11,
136 ),
137 ),
138 ),
139 ],
140 ),
141 ),
142 ),
143 onPressed: () {
144 if (listItems != null) {
145 Navigator.push(
146 context,
147 MaterialPageRoute(
148 builder: (context) => CastProfileDetail(),
149 ),
150 );
151 }
152 },
153 );
154 },
155 ),
156 ),
157 ],
158 ),
159 );
160 }
161}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/13 13:24