【问题标题】:Flutter - How to build a list view with expandable panels containing forms?Flutter - 如何使用包含表单的可扩展面板构建列表视图?
【发布时间】:2018-08-08 17:15:35
【问题描述】:

我正在尝试在列表视图的可展开面板中构建表单。

我想我已经接近了,但我一直遇到关于视口高度错误的问题。错误是这样说的:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ The following assertion was thrown during performResize(): Vertical viewport was given unbounded height. Viewports expand in the scrolling direction to fill their container.In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget. If this widget is always nested in a scrollable widget there is no need to use a viewport because there will always be enough vertical space for the children. In this case, consider using a Column instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size the height of the viewport to the sum of the heights of its children.

从几个在线资源中,我想出了将每个表单创建为小部件并创建列表视图包含的可扩展面板列表的想法。列表视图是应用程序的主体。

到目前为止,我的代码如下所示:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'App',
      home: Interview(),
    );
  }
}

class Interview extends StatefulWidget {
  @override
  InterviewState createState() => new InterviewState();
}

class ExpansionPanelRow {
  bool isExpanded;
  final String header;
  final Widget body;
  final Icon icon;
  ExpansionPanelRow(this.isExpanded, this.header, this.body, this.icon);
}

class InterviewState extends State<Interview> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
  List<String> _colors = <String>['', 'red', 'green', 'blue', 'orange'];
  String _color = '';

  Widget interviewDataForm() {
    return new SafeArea(
          top: false,
          bottom: false,
          child: Form(
            key: _formKey,
            autovalidate: true,
            child: new ListView(
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              children: <Widget>[
                new TextFormField(
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.person),
                    hintText: 'Enter your first and last name',
                    labelText: 'Name',
                  ),
                ),
                new TextFormField(
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.calendar_today),
                    hintText: 'Enter your date of birth',
                    labelText: 'Dob',
                  ),
                  keyboardType: TextInputType.datetime,
                ),
                new TextFormField(
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.phone),
                    hintText: 'Enter a phone number',
                    labelText: 'Phone',
                  ),
                  keyboardType: TextInputType.phone,
                  inputFormatters: [
                    WhitelistingTextInputFormatter.digitsOnly,
                  ],
                ),
                new TextFormField(
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.email),
                    hintText: 'Enter a email address',
                    labelText: 'Email',
                  ),
                  keyboardType: TextInputType.emailAddress,
                ),
                new InputDecorator(
                  decoration: const InputDecoration(
                    icon: const Icon(Icons.color_lens),
                    labelText: 'Color',
                  ),
                  isEmpty: _color == '',
                  child: new DropdownButtonHideUnderline(
                    child: new DropdownButton<String>(
                      value: _color,
                      isDense: true,
                      onChanged: (String newValue) {
                        setState(() {
                          _color = newValue;
                        });
                      },
                      items: _colors.map((String value) {
                        return new DropdownMenuItem<String>(
                          value: value,
                          child: new Text(value),
                        );
                      }).toList(),
                    ),
                  ),
                ),
                new Container(
                    padding: const EdgeInsets.only(left: 40.0, top: 20.0),
                    child: new RaisedButton(
                      child: const Text('Submit'),
                      onPressed: null,
                    )),
              ],
            )
          )
        );
  }

  List<ExpansionPanelRow> getRows() {
    return <ExpansionPanelRow>[
      new ExpansionPanelRow(
          false,
          'Schools',
          new Padding(
              padding: new EdgeInsets.all(20.0),
              child: interviewDataForm()
          ),
          new Icon(
            Icons.call,
            size: 18.0,
            color: Color(0xFF42A5F5)
          )
      ),
      new ExpansionPanelRow(
          false,
          'Schools',
          new Padding(
              padding: new EdgeInsets.all(20.0),
              child: new Column(children: <Widget>[])
          ),
          new Icon(
            Icons.call,
            size: 18.0,
            color: Color(0xFF42A5F5)
          )
      ),
    ];
  }

  ListView listCriteria;

  Widget build(BuildContext context) {
    listCriteria = new ListView(
      children: [
        new Padding(
          padding: new EdgeInsets.all(10.0),
          child: new ExpansionPanelList(
            expansionCallback: (int index, bool isExpanded) {
              setState(() {
                getRows()[index].isExpanded = !getRows()[index].isExpanded;
              });
            },
            children: getRows().map((ExpansionPanelRow row) {
              return new ExpansionPanel(
                headerBuilder: (BuildContext context, bool isExpanded) {
                  return new ListTile(
                      leading: row.icon,
                      title: new Text(
                        row.header,
                        textAlign: TextAlign.left,
                        style: new TextStyle(
                          fontSize: 20.0,
                          fontWeight: FontWeight.w400,
                        ),
                      ));
                },
                isExpanded: row.isExpanded,
                body: row.body,
              );
            }).toList(),
          ),
        )
      ],
    );

  Scaffold scaffold = new Scaffold(
      appBar: new AppBar(
        title: new Text("App"),
      ),
      body: listCriteria,
      persistentFooterButtons: <Widget>[
        new ButtonBar(children: <Widget>[
          new FlatButton(
            color: Colors.blue,
            onPressed: null,
            child: new Text(
              'Add',
              textAlign: TextAlign.left,
              style: new TextStyle(fontWeight: FontWeight.bold),
            ),
          )
        ])
      ],
    );
    return scaffold;
  }
}

在哪个Widget中定义高度更好?我应该在所有小部件中定义高度吗?

【问题讨论】:

    标签: android ios dart flutter


    【解决方案1】:

    正如错误所说:

    如果此小部件始终嵌套在可滚动小部件中,则无需使用视口,因为 孩子们总会有足够的垂直空间。在这种情况下,请考虑使用 Column 反而。否则,请考虑使用“shrinkWrap”属性(或 ShrinkWrappingViewport)将视口的高度调整为其子项的高度之和。

    要解决这个错误添加shrinkWrap: true:

     Widget interviewDataForm() {
    return new SafeArea(
        top: false,
        bottom: false,
        child: Form(
            key: _formKey,
            autovalidate: true,
            child: new ListView(
              shrinkWrap: true,
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
              children: <Widget>[
    

    【讨论】:

    • 谢谢,现在错误已修复。然而,可扩展面板并未显示内部形式。知道为什么不显示吗?
    • 不知道,您需要调试代码并检查。如果你写 isExpanded=true 它将显示表单,但是即使显示或不显示表单,单击箭头也不起作用。
    猜你喜欢
    • 2021-02-16
    • 2018-01-15
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多