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

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

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

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

Dart

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

Q&A

解決済

1回答

2824閲覧

Flutterでデータを読み込むまで画像やテキストを灰色にしたい

Yariii

総合スコア61

Flutter

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

Dart

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

0グッド

0クリップ

投稿2020/09/13 04:30

編集2020/09/13 04:31

FlutterでDBからデータを取得して表示する場合、データが表示されるまでその箇所をグレーアウトしておくにはどのように実現するのでしょうか?

現在スタッフ一覧を表示するコードを書いていて(DBは仮で存在するていで書いています)、今回は実験的に、「スタッフ写真」の箇所だけ実現してみたいと考えています。

?と:の分岐を使って、グレーアウト用と写真用のエリアは用意できました。ここからDB取得後、setStateで写真をセットするイメージで考えているのですが、上手く書き方を想像できなくて、、

ちなみに以下のコードは、既にDBから情報が配列に入っている前提で書いています。(DB取得の経験がないため、取得するためのコードの書き方も、文献を参考にしてもピンとこなくて...)

class ListViewHorizonCast extends StatelessWidget { //データ(仮) final List<Map<String, dynamic>> listItems = [ { 'name': '山本太郎', 'img': '../assets/images/sample.jpg', 'comment': 'ここに一言入ります', 'age': '22' + '歳', }, { 'name': '山本花子', 'img': '../assets/images/sample.jpg', 'comment': 'ここに一言入ります', 'age': '22' + '歳', }, { 'name': '田中花子', 'img': '../assets/images/sample.jpg', 'comment': 'ここに一言入ります', 'age': '22' + '歳', }, ]; @override Widget build(BuildContext context) { return Container( color: Colors.white, margin: EdgeInsets.only(top: 10.0), padding: EdgeInsets.symmetric( horizontal: Settings().sidePadding(), vertical: 20, ), child: Column( children: <Widget>[ //タイトル Container( width: double.infinity, margin: EdgeInsets.only(top: 0.0, bottom: 0.0), height: 30, child: Text( 'スタッフ一覧', style: Settings.fontTitleStyle, textAlign: TextAlign.left, ), ), //カードリスト Container( height: 200, padding: EdgeInsets.only(bottom: 15.0), child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: listItems.length, itemBuilder: (context, index) { //カード return FlatButton( child: SizedBox( width: 150, child: Card( child: Stack( fit: StackFit.expand, children: <Widget>[ //スタッフの写真 Container( child: listItems == true //グレーアウト ? Container() //データ取得後の写真表示 : Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage( '../assets/images/sample.jpg'), fit: BoxFit.cover, ), ), child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: [0.5, 0.75, 0.95], colors: [ Colors.black12, Colors.black54, Colors.black87, ], ), ), )), ), //スタッフの名前 Positioned( bottom: 25.0, left: 5.0, child: Text( listItems[index]['name'], style: TextStyle( color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold), ), ), //スタッフの一言 Positioned( bottom: 8.0, left: 5.0, child: Text( listItems[index]['comment'], style: TextStyle(color: Colors.white70, fontSize: 11), ), ), ], )), ), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => CastProfileDetail(), )); }, ); }, ), ), ], ), ); } }

以上になります。
このコード内の変数「listItems」を操作して、DB取得後、setStateで切り替えるイメージではいるのですが、どのようにするのでしょうか?
ご教授のほど、よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

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 24 _StuffListSectionState createState() => _StuffListSectionState(); 25} 26 27class _StuffListSectionState extends State<StuffListSection> { 28 29 Future<List<Map<String, dynamic>>> staffs; // 取得したデータを保持するための変数 30 31 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 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 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 3 _ListViewHorizonCastState createState() => _ListViewHorizonCastState(); 4} 5 6class _ListViewHorizonCastState extends State<ListViewHorizonCast> { 7 List<Map<String, dynamic>> listItems; 8 9 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 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 08:19

編集2020/09/13 12:37
nskhei

総合スコア704

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

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

Yariii

2020/09/13 13:24

お返事が遅くなりました。 具体的なコードまで書いてくださり、大変ありがとうございます。 上記コードを参考に組み直したところ、とても満足のいく結果となりました。感激です。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問