bugfix> android > 投稿

下のスクリーンショットのようにFlutterを使用して展開可能なListViewを作成する方法は?

ExpansionTiles のスクロール可能なリストビューを作成したい 展開すると、スクロールできないリストビューが表示されます。

ExpansionTiles のリストビューを実装しようとしましたその中に listView.builder(...) を使用して別のリストビューをネストしました 。しかし、 ExpansionTile を展開したときリストビューが表示されませんでした...

(スクリーンショットは説明のためのものです)  

Flutterで同様の出力を取得する方法はありますか?

編集: 私のソースコード:

import 'package:flutter/material.dart';
void main() => runApp(
  new MaterialApp(
    home: new MyApp(),
  )
);
var data = {
  "01/01/2018": [
    ["CocaCola", "\$ 5"],
    ["Dominos Pizza", "\$ 50"],
  ],
  "04/01/2018": [
    ["Appy Fizz", "\$ 10"],
    ["Galaxy S9+", "\$ 700"],
    ["Apple iPhone X", "\$ 999"],
  ],
};
List<String> dataKeys = data.keys.toList();
String getFullDate(String date) {
  List<String> dateSplit = date.split('/');
  List<String> months = ["Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"];
  return "${dateSplit[0]} ${months[int.parse(dateSplit[1]) - 1]} ${dateSplit[2]}";
}
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
  List<Widget> _buildList(int keyIndex) {
    List<Widget> list = [];
    for (int i = 0; i < data[dataKeys[keyIndex]].length; i++) {
      list.add(
        new Row(
          children: <Widget>[
            new CircleAvatar(
              child: new Icon(Icons.verified_user),
              radius: 20.0,
            ),
            new Text(data[dataKeys[keyIndex]][i][0])
          ],
        )
      );
    }
    return list;
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Expense Monitor"),
      ),
      body: new Container (
        child: new ListView.builder(
          itemCount: dataKeys.length,
          itemBuilder: (BuildContext context, int keyIndex) {
            return new Card(
              child: new ExpansionTile(
                title: new Text(getFullDate(dataKeys[keyIndex])),
                children: <Widget>[
                  new Column(
                    children: _buildList(keyIndex)
                  )
                ]
              ),
            );
          }
        )
      )
    );
  }
}

コンソールに表示されるエラー:

I/flutter (12945): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (12945): The following assertion was thrown during performResize():
I/flutter (12945): Vertical viewport was given unbounded height.
I/flutter (12945): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (12945): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (12945): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (12945): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (12945): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (12945): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (12945): the height of the viewport to the sum of the heights of its children.
I/flutter (12945): When the exception was thrown, this was the stack:
I/flutter (12945): #0      RenderViewport.performResize.<anonymous closure> (package:flutter/src/rendering/viewport.dart:944:15)
I/flutter (12945): #1      RenderViewport.performResize (package:flutter/src/rendering/viewport.dart:997:6)
I/flutter (12945): #2      RenderObject.layout (package:flutter/src/rendering/object.dart:1555:9)
I/flutter (12945): #3      _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:109:13)
......
I/flutter (12945): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (12945): Another exception was thrown: RenderBox was not laid out: RenderViewport#df29c NEEDS-LAYOUT NEEDS-PAINT

回答 2 件
  • これを試して:

    import 'package:flutter/material.dart';
    void main() => runApp(new MaterialApp(home: new MyApp(), debugShowCheckedModeBanner: false,),);
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    }
    class _MyAppState extends State<MyApp> {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          body: new ListView.builder(
            itemCount: vehicles.length,
            itemBuilder: (context, i) {
              return new ExpansionTile(
                title: new Text(vehicles[i].title, style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),),
                children: <Widget>[
                  new Column(
                    children: _buildExpandableContent(vehicles[i]),
                  ),
                ],
              );
            },
          ),
        );
      }
      _buildExpandableContent(Vehicle vehicle) {
        List<Widget> columnContent = [];
        for (String content in vehicle.contents)
          columnContent.add(
            new ListTile(
              title: new Text(content, style: new TextStyle(fontSize: 18.0),),
              leading: new Icon(vehicle.icon),
            ),
          );
        return columnContent;
      }
    }
    class Vehicle {
      final String title;
      List<String> contents = [];
      final IconData icon;
      Vehicle(this.title, this.contents, this.icon);
    }
    List<Vehicle> vehicles = [
      new Vehicle(
        'Bike',
        ['Vehicle no. 1', 'Vehicle no. 2', 'Vehicle no. 7', 'Vehicle no. 10'],
        Icons.motorcycle,
      ),
      new Vehicle(
        'Cars',
        ['Vehicle no. 3', 'Vehicle no. 4', 'Vehicle no. 6'],
        Icons.directions_car,
      ),
    ];
    
    

  • これを試して!

    最初にExpandableContainer AnimatedContainerを使用します。

    次に、ExpandableListViewを作成します。カラム 。列の最初の子は展開するボタンになり、2番目の子はボタンになりますExpandableContainer 。 ExpandableContainer がありますリストビュー その子として。

    最後のステップは、リストビュー のExpandableListView

    結果 :

    コード :

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    void main() {
      runApp(new MaterialApp(home: new Home()));
    }
    class Home extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          backgroundColor: Colors.grey,
          appBar: new AppBar(
            title: new Text("Expandable List"),
            backgroundColor: Colors.redAccent,
          ),
          body: new ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return new ExpandableListView(title: "Title $index");
            },
            itemCount: 5,
          ),
        );
      }
    }
    class ExpandableListView extends StatefulWidget {
      final String title;
      const ExpandableListView({Key key, this.title}) : super(key: key);
      @override
      _ExpandableListViewState createState() => new _ExpandableListViewState();
    }
    class _ExpandableListViewState extends State<ExpandableListView> {
      bool expandFlag = false;
      @override
      Widget build(BuildContext context) {
        return new Container(
          margin: new EdgeInsets.symmetric(vertical: 1.0),
          child: new Column(
            children: <Widget>[
              new Container(
                color: Colors.blue,
                padding: new EdgeInsets.symmetric(horizontal: 5.0),
                child: new Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    new IconButton(
                        icon: new Container(
                          height: 50.0,
                          width: 50.0,
                          decoration: new BoxDecoration(
                            color: Colors.orange,
                            shape: BoxShape.circle,
                          ),
                          child: new Center(
                            child: new Icon(
                              expandFlag ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
                              color: Colors.white,
                              size: 30.0,
                            ),
                          ),
                        ),
                        onPressed: () {
                          setState(() {
                            expandFlag = !expandFlag;
                          });
                        }),
                    new Text(
                      widget.title,
                      style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
                    )
                  ],
                ),
              ),
              new ExpandableContainer(
                  expanded: expandFlag,
                  child: new ListView.builder(
                    itemBuilder: (BuildContext context, int index) {
                      return new Container(
                        decoration:
                            new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.grey), color: Colors.black),
                        child: new ListTile(
                          title: new Text(
                            "Cool $index",
                            style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
                          ),
                          leading: new Icon(
                            Icons.local_pizza,
                            color: Colors.white,
                          ),
                        ),
                      );
                    },
                    itemCount: 15,
                  ))
            ],
          ),
        );
      }
    }
    class ExpandableContainer extends StatelessWidget {
      final bool expanded;
      final double collapsedHeight;
      final double expandedHeight;
      final Widget child;
      ExpandableContainer({
        @required this.child,
        this.collapsedHeight = 0.0,
        this.expandedHeight = 300.0,
        this.expanded = true,
      });
      @override
      Widget build(BuildContext context) {
        double screenWidth = MediaQuery.of(context).size.width;
        return new AnimatedContainer(
          duration: new Duration(milliseconds: 500),
          curve: Curves.easeInOut,
          width: screenWidth,
          height: expanded ? expandedHeight : collapsedHeight,
          child: new Container(
            child: child,
            decoration: new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.blue)),
          ),
        );
      }
    }
    
    

あなたの答え