【问题标题】:How to fix "BoxConstraints forces an infinite width" and how to delete an item from a list?如何修复“BoxConstraints 强制无限宽度”以及如何从列表中删除项目?
【发布时间】:2019-05-26 10:08:13
【问题描述】:

我是 Flutter 的初学者,但由于“布局问题”而无法得到我想要的结果。我尝试了好几个小时...


技术问题:
当我单击“添加播放器按钮”以添加新的 TextField 以设置更多播放名称时,出现错误:“BoxConstraints 强制无限宽度”。所以,TextField 没有显示出来。


其他我不知道如何实现的功能:
- 我有一个“下拉菜单”来选择难度游戏。为什么不显示默认文本(难度:正常)?
- 怎么做:当用户点击图标“remove”(见TextField上的suffixIcon),那么对应的fieldText就被删除了?
- 如何做到这一点:当用户单击添加播放器时,默认提示文本会增加(播放器 2、播放器 3、播放器 4 ......)? - 为什么当用户滚动页面时我的背景渐变没有修复? (就像在 HTML/CSS '背景附件:固定')?

import 'package:flutter/material.dart';

/// Styles

///




class Homepage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyHomePageState();
  }
}


class _MyHomePageState extends State<Homepage> {

  String dropdownValue = 'Normal';

  List<TextField> _playerList = new List(); //_playerList is my List name
  int playerListIndex = 0; //Count the number of times "Add" button clicked

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Stack(children: <Widget>[
        // To have a gradient background
        new Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          decoration: new BoxDecoration(
            gradient: new LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: [0.1, 1],
              colors: [
                Colors.redAccent[200],
                Colors.red[300],
              ],
              tileMode:
                  TileMode.repeated,
            ),
          ),

          //I need SingleChildScrollView to haven't "Overflow yellow bar on bottom screen"
          child: SingleChildScrollView(

            child: Container(

              padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  mainAxisSize: MainAxisSize.min,

                  children: <Widget>[
                    // Box to add big image
                    SizedBox(
                      height: 450,
                    ),



                    // DROP DOWN MENU to choose difficulty  modes
                    InputDecorator(
                      decoration: InputDecoration(
                        prefixIcon: const Icon(Icons.games),
                        filled: true,
                      ),
                      child: DropdownButtonHideUnderline(
                        child: new DropdownButton<String>(
                          value: dropdownValue,
                          hint: Text('Difficulty normal'),
                          isDense: true,
                          items: <String>['Normal', 'Easy', 'Hard']
                              .map<DropdownMenuItem<String>>((String value) {
                            return DropdownMenuItem<String>(
                              value: value,
                              child: Text(value),
                            );
                          }).toList(),
                          onChanged: (String newValue) {
                            setState(() {
                              dropdownValue = newValue;
                            });
                          },
                        ),
                      ),
                    ),

                    //Field player name 1. At least I need 1 player
                        new TextField(
                          maxLength: 20,
                          decoration: InputDecoration(
                            prefixIcon: const Icon(Icons.person),
                            filled: true,
                            hintText:"Player 1",
                            counterText: "",
                          ),
                        ),


                    //Field for other player name 2, 3, 4, ...
                    new ListView.builder(
                      padding: EdgeInsets.all(0),
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: _playerList.length,
                      itemBuilder: (context, index) {
                        TextField widget = _playerList.elementAt(index);
                        return widget;
                      }),

                    //Button to add other field text to set player name. The user can delete a player on click on "clear icon button"
                    new Align(
                      alignment: Alignment.centerRight,
                      child: FlatButton.icon(
                          color: Colors.black,
                          icon: Icon(
                            Icons.add,
                            color: Colors.white,
                            size: 18,
                          ),
                          label: Text('Add player',
                              style:
                                  TextStyle(fontSize: 12, color: Colors.white)),
                          onPressed: () {
                            setState(() {
                              playerListIndex++;
                              _playerList.add(
                                    new TextField(
                                      maxLength: 20,
                                      decoration: InputDecoration(
                                        prefixIcon: const Icon(Icons.person),
                                        suffixIcon: new IconButton(
                                            icon: Icon(Icons.clear),
                                            onPressed: () {
                                              _playerList.removeAt(playerListIndex); //Doesn't work
                                            }),
                                        filled: true,
                                        hintText: "Player $playerListIndex", //Doesn't work i would like Player 2, Player 3, ...
                                        counterText: "",
                                      ),
                                    ),
                              );
                              print(playerListIndex);
                              print(_playerList);
                              print(_playerList[0]);
                            });
                          }),
                    ),
                    new ButtonTheme(
                      minWidth: 350,
                      height: 45,
                      child: FlatButton(
                        color: Colors.black,
                        child: Text('Play',
                            style:
                                TextStyle(fontSize: 18, color: Colors.white)),
                        onPressed: () {
                          // Perform some action
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ]),
    );
  }


}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我想我明白发生了什么。让我们开始吧:

    首先。您的TextField 没有出现,并且您收到错误消息,因为您没有为其设置宽度和高度,因此,它正在尝试获得最大尺寸。解决方案?将其包裹在 Container 小部件(或 SizedBox)中,并为其指定宽度和高度。这应该可以解决第一个问题。

    第二。您的 DropDownMenu 的提示文本(难度正常)未显示,因为您没有在 DropDown 小部件See the hint propierty below 中传递参数“提示”。

    第三。您想在单击后缀时清除TextField 字符串,对吗?为此,传递GestureDetectorIconButton 作为后缀组件,创建TextEditingController 并在控制器部分的TextField 中传递它,然后在onPressed/onTap 方法上(取决于哪个您将设置的小部件)设置:_textController.text.clear() 方法,在 setState 函数 内。这应该可以解决问题。

    第四。您希望玩家的字符串列表随着您添加更多玩家而增加,对吗?你有很多方法可以做到这一点,其中一种是创建一个空列表,你可以模拟来测试它,然后,每次点击“添加播放器”按钮,你都会添加一个与 for 中的值对应的字符串循环将 for 的索引作为“Player $index”中的 int 值传递。同样,for 方法将接收一个 setState 方法,并且在 setState 中,您的逻辑是添加一个更多的 Player。

    最后,你的渐变没有保持固定?嗯,我认为您可以在名为 resizeToAvoidBottomInset 的 Scaffold 小部件中传递一个属性并将其设置为 false。

    如果某些事情没有按您的预期工作,请回复,我会帮助您。

    【讨论】:

    • 感谢您的回答,我会做出更改并通知您。对于第 3 部分,我想删除文本字段,而不仅仅是清除文本。 (从列表“_playerList”中删除当前 TextField 类似 playerList.remove (current_index);(与添加按钮功能相反)
    • 我知道,如果你想删除,你会有一些解决方法,比如使用 setState 来验证列表的某些索引是否已被删除,然后,将 TextField 更改为空容器,我相信在你。要从列表中删除一个项目,您首先要检查它是否在列表中,如果是,请使用 .removeAt(index) 方法并查看它是否有效。
    • 仅供参考:我解决了第一点,单击添加按钮时会出现文本字段。但是这种行为正在剥离:如果我从新添加的字段滚动,那么我无法滚动页面。请参阅带有“蓝色区域”的更新图片。第二个还不行,我加了这个代码提示: Text ('Difficulty normal') ,。我在第一篇文章中更新了源代码第三,我添加了 _playerList.removeAt (index);但未定义索引。第四,我还没有寻找解决方案。我继续
    • 它不会滚动,因为您有两个具有相同行为的组件:SingleChildScrollView 和 ListView.builder()。要更改下拉列表中的文本,您不能直接在 Text 组件中传递硬编码字符串,您必须像这样传递:Text(myString),然后,在 DropDown 内的 onChanged 方法上执行:onChanged: ( String value) => setState(() => myString = value);您将使用 for 循环获取索引,index, i,interate 的变量名
    • 我解决了第一点,我添加了shrinkWrap: truephysics: NeverScrollableScrollPhysics(),。但是当我点击“X”按钮时,我很难从 _playerList 中删除一个项目
    猜你喜欢
    • 2019-02-25
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2020-12-22
    • 2020-04-27
    相关资源
    最近更新 更多