Flutter:当其他小部件可用时,ListView 的高度会降低

Posted

技术标签:

【中文标题】Flutter:当其他小部件可用时,ListView 的高度会降低【英文标题】:Flutter: ListView height is getting reduced when other widgets are available 【发布时间】:2020-06-23 10:03:46 【问题描述】:

我正在开发一个颤振应用程序,并在那里动态生成checkboxes 的列表。为此,我使用了ListView.Builder

下面是我的完整代码,你可以轻松实现它。

import 'package:flutter/material.dart';

class AddAccountPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text("Services"),
        actions: <Widget>[
          FlatButton(
            child: Text(
              "Save",
              style: Theme.of(context).textTheme.button,
            ),
            onPressed: () ,
          )
        ],
      ),
      body: SingleChildScrollView(
          child: ConstrainedBox(
        constraints:
            BoxConstraints(maxHeight: MediaQuery.of(context).size.height),
        child: Container(
          child: _AddAccountUI(),
        ),
      )),
    );
  


class _AddAccountUI extends StatefulWidget 
  @override
  State<StatefulWidget> createState() 
    // TODO: implement createState
    return _AddAccountState();
  


class _AddAccountState extends State<_AddAccountUI> 
  List<int> checkBoxElements = [];
  List<String> checkBoxStrings =['one','two','three','four'];

  bool _onTheSpotServices=false;
  bool _homeVisits=false;

  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          margin: EdgeInsets.all(10),
          child: Text(
            "Let's add your company into the system. Just fill out the form below.",
            style: Theme.of(context).textTheme.subtitle,
          ),
        ),
        _imageSelector(),
        Container(
          margin: EdgeInsets.all(20),
          child: Text(
            "Company Name",
            style: Theme.of(context).textTheme.body1,
          ),
        ),
        Container(
          margin: EdgeInsets.only(top: 5, left: 15),
          child: SizedBox(
            height: 36,
            width: MediaQuery.of(context).size.width * .90,
            child: TextFormField(
              validator: (value) 
                if (value.isEmpty) 
                  return 'Please enter some text';
                
                return null;
              ,
              decoration: InputDecoration(
                filled: true,
                fillColor: Colors.white,
                contentPadding:
                    const EdgeInsets.only(top: 2, bottom: 2, left: 8),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30.0),
                ),
              ),
            ),
          ),
        ),
        Container(
          margin: EdgeInsets.only(top: 30, left: 20),
          child: Text(
            "Business Type",
            style: Theme.of(context).textTheme.body1,
          ),
        ),
        Container(
          margin: EdgeInsets.only(top: 10, left: 20),
          child: SizedBox(
            height: 36,
            width: MediaQuery.of(context).size.width * .90,
            child: DropdownButton<String>(
              hint: Text(
                "Please Select",
                style: Theme.of(context).textTheme.body1,
              ),
              items:
                  <String>['Foo000000000', 'Bar00000000'].map((String value) 
                return new DropdownMenuItem<String>(
                  value: value,
                  child: new Text(
                    value,
                    style: Theme.of(context).textTheme.body1,
                  ),
                );
              ).toList(),
              onChanged: (_) ,
            ),
          ),
        ),
        Container(
          margin: EdgeInsets.only(top: 30, left: 20, bottom: 10),
          child: Text(
            "Category",
            style: Theme.of(context).textTheme.body1,
          ),
        ),

        Expanded(
          child: Container(
              margin: EdgeInsets.only(left: 15),
              child: ListView.builder(
                  itemCount: 4,
                  itemBuilder: (BuildContext context, int index) 
                    return _TickBox(checkBoxElements, index);
                  )),
        ),
        Container(
          margin: EdgeInsets.only(top: 30, left: 20, bottom: 20),
          child: Text(
            "Location",
            style: Theme.of(context).textTheme.body1,
          ),
        ),
        Container(
          margin: EdgeInsets.only(top: 5, left: 15),
          child: SizedBox(
            height: 36,
            width: MediaQuery.of(context).size.width * .90,
            child: TextFormField(
              validator: (value) 
                if (value.isEmpty) 
                  return 'Please enter some text';
                
                return null;
              ,
              decoration: InputDecoration(
                filled: true,
                fillColor: Colors.white,
                contentPadding:
                    const EdgeInsets.only(top: 2, bottom: 2, left: 8),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30.0),
                ),
              ),
            ),
          ),
        ),
        Container(child: _switchMaker(),),
        SizedBox(
          height: 50,
        )
      ],
    );
  

  Widget _imageSelector() 
    return GestureDetector(
        onTap: () ,
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
              width: 1,
              color: Color.fromRGBO(212, 208, 208, 100),
            ),
            color: Color.fromRGBO(242, 242, 242, 100),
          ),
          width: double.infinity,
          height: MediaQuery.of(context).size.height * .3,
          child: Center(child: Text("Add Your Cover Photo")),
        ));
  

  Widget _switchMaker() 
    return Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            Container(
              margin: EdgeInsets.only(top: 20, left:20),
                          child: Text(
                "Provide on the spot services",
                style: Theme.of(context).textTheme.body1,
              ),
            ),
            Spacer(flex: 1,),
            Container(margin: EdgeInsets.only(top:20, right: 20),
                          child: Text(
                "Make Home Visits",
                style: Theme.of(context).textTheme.body1,
              ),
            )
          ],
        ),
        Row(children: <Widget>[
          Container(
            margin: EdgeInsets.only(top: 10, left: 20),
            child: Switch(value: _onTheSpotServices, onChanged: (bool value) 
              setState(() 
                _onTheSpotServices=value;
              );
            , )),
          Spacer(flex: 1,),
          Container(
            margin: EdgeInsets.only(top:10, right:20),
            child: Switch(value: _homeVisits, onChanged: (bool value) 
              setState(() 
                _homeVisits=value;
              );
            , )),
        ],)
      ],
    );
  


class _TickBox extends StatefulWidget 
  List<int> checkBoxElements = [];
  int dataValue = 0;

  _TickBox(List<int> elements, int value) 
    checkBoxElements = elements;
    dataValue = value;
  

  @override
  State<StatefulWidget> createState() 
    // TODO: implement createState
    return _TickBoxState();
  


class _TickBoxState extends State<_TickBox> 
  bool value = false;

  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return Container(
      child: CheckboxListTile(
        title: Text(
          "Garage shop with general repair",
          style: Theme.of(context).textTheme.body1,
        ),
        onChanged: (bool val) 
          setState(() 
            value = val;

            if (widget.checkBoxElements.contains(widget.dataValue)) 
              widget.checkBoxElements.remove(widget.dataValue);
             else 
              widget.checkBoxElements.add(widget.dataValue);
            

            print(widget.checkBoxElements);
          );
        ,
        value: value,
        controlAffinity: ListTileControlAffinity.leading,
      ),
    );
  

现在的问题是,ListView.Builder 生成的项目被完全压缩,只有一个项目是可见的。要查看其余部分,您必须滚动。

我尝试使用physics: const NeverScrollableScrollPhysics()shrinkWrap:false 来停止滚动。它确实有效,但是项目仍然被压缩。

这就是它的样子。要选中复选框,请查看 Category

我需要在不滚动的情况下完整显示这些项目。我该怎么做?

【问题讨论】:

当您有两个可滚动项时会发生这种情况。您可以通过在构建布局时设置第二个列表的大小来修复它,或者在项目大小发生变化时以编程方式修复它。或者找到一种不同的方式来设计不需要两个可滚动项的布局。 @maja89 我不需要 2 个滚动项。我只需要滚动完整视图,而不是复选框。如果在颤振中有另一种方法可以在循环中构建复选框而不是“ListView”0我很乐意使用。 【参考方案1】:

您需要删除Expanded 小部件并在ListView.builder 中添加以下属性:

      Container(
        child: ListView.builder(
        shrinkWrap: true,
        physics: const NeverScrollableScrollPhysics(),
        itemCount: 4,
        itemBuilder: (BuildContext context, int index) 
          return _TickBox(checkBoxElements, index);
        ),
      ),

【讨论】:

谢谢。我试过了。然后它对问题进行了排序,但最终以overflow 问题结束,它显示黄色条纹【参考方案2】:

使用“SingleChildScrollView”。这应该让你继续前进!

【讨论】:

以上是关于Flutter:当其他小部件可用时,ListView 的高度会降低的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 文本小部件

javascript 将样式表附加到iframe内容(例如Twitter小部件) - 这很脏,但是当没有其他选项可用时它很有效。

Flutter 使用 Stack 或任何其他方法重叠具有动态高度的多个小部件

为啥当我在其小部件中调用 Flutter 有状态小部件时,它没有改变另一个有状态小部件的状态

当 Flutter 中的全局变量更改(异步)时更新小部件

当孩子是芯片小部件时,Flutter MouseRegion 不起作用