ScrollView RenderFlex 溢出 - Flutter

Posted

技术标签:

【中文标题】ScrollView RenderFlex 溢出 - Flutter【英文标题】:ScrollView RenderFlex overflow - Flutter 【发布时间】:2021-11-17 01:44:06 【问题描述】:

我是 Flutter 的新手,一直在尝试克隆需要滚动架构的屏幕。这是我正在处理的屏幕的链接。 https://i.stack.imgur.com/1OW2b.png代码如下。PS:不完整的字段请忽略。获得滚动视图后,我将在之后添加功能。

Scaffold(
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: const <Widget>[
                        Icon(Icons.menu),
                        Image(),       //Asset image
                      ],
                    ),
                    Row(
                      children: <Widget>[
                        const Icon(Icons.notifications_none),
                        const SizedBox(width: 27.0),
                        CircleAvatar(
                          child: Text("JM"),
                        ),
                      ],
                    )
                  ],
                ),
                Row(
                  children: const <Widget>[
                    Icon(Icons.arrow_back),
                    SizedBox(width: 20.0),
                    Text("Public page"),
                  ],
                ),
                const SizedBox(
                  height: 20.0,
                ),
                const Text("  Please fill the form following the proper order."),
                const SizedBox(height: 10.0),

                OverviewWidget(), //Widget with lots of TextFormField
                SizedBox(height: 10.0),
                DescriptionWidget(), //Widget with lots of TextFormField

              ],
            ),
          ),
          Align([enter image description here][1]
            alignment: Alignment.bottomCenter,
            child: GestureDetector(
              onTap: () 
                print("Hello");
              ,
              child: Container(
                height: 130.0,
                width: double.infinity,
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: Colors.white,
                  boxShadow: [
                    BoxShadow(
                      color: Colors.grey.shade400,
                      blurRadius: 10,
                      spreadRadius: 1,
                    )
                  ],
                ),
                child: Container(
                  margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
                  decoration: BoxDecoration(
                    color: Colors.green.shade400,
                    borderRadius: BorderRadius.circular(35),
                  ),
                  child: const Padding(
                    padding: EdgeInsets.symmetric(
                      vertical: 15.0,
                      horizontal: 150.0,
                    ),
                    child: Text(
                      "Save",
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 17,
                          fontWeight: FontWeight.w600),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );

到目前为止,我只创建了 OverviewDescription 小部件并且我已经收到了 RenderFlex overflow 错误。我尝试用SingleChildScrollView 小部件包装第一个Column 小部件,但可以注意到底部的Save 按钮应该保持固定。我尝试用 Stack 小部件而不是 Column 小部件包装整个小部件,但它也没有帮助。我也使用了ListView 小部件,但得到了相同的结果。我应该怎么做才能实现这个视图?

【问题讨论】:

【参考方案1】:

我猜你拥有所有元素,但没有完全按照需要使用它们。

你的屏幕由两个重要的布局组成:

堆栈(包含可滚动小部件顶部的按钮) 可滚动小部件

堆栈必须是堆栈,可滚动可以是任何东西,但在您的情况下 SingleChildScrollView+Column 似乎是最佳选择。

具体实现如下:

Scaffold(
  body: Stack(
    children: <Widget>[
      Padding(
        padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.only(bottom: 100.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        Icon(Icons.menu),
                        Container(
                          height: 100,
                          width: 100,
                          color: Colors.redAccent,
                        ),
                        //Asset image
                      ],
                    ),
                    Row(
                      children: <Widget>[
                        const Icon(Icons.notifications_none),
                        const SizedBox(width: 27.0),
                        CircleAvatar(
                          child: Text("JM"),
                        ),
                      ],
                    )
                  ],
                ),
                Row(
                  children: const <Widget>[
                    Icon(Icons.arrow_back),
                    SizedBox(width: 20.0),
                    Text("Public page"),
                  ],
                ),
                const SizedBox(
                  height: 20.0,
                ),
                const Text("  Please fill the form following the proper order."),
                const SizedBox(height: 10.0),

                Container(
                  height: 400,
                  color: Colors.blueAccent,
                ), //Widget with lots of TextFormField
                SizedBox(height: 10.0),
                Container(
                  height: 400,
                  color: Colors.greenAccent,
                ), //Widget with lots of TextFormField
              ],
            ),
          ),
        ),
      ),
      Align(
        alignment: Alignment.bottomCenter,
        child: GestureDetector(
          onTap: () 
            print("Hello");
          ,
          child: Container(
            height: 130.0,
            width: double.infinity,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: Colors.white,
              boxShadow: [
                BoxShadow(
                  color: Colors.grey.shade400,
                  blurRadius: 10,
                  spreadRadius: 1,
                )
              ],
            ),
            child: Container(
              margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
              decoration: BoxDecoration(
                color: Colors.green.shade400,
                borderRadius: BorderRadius.circular(35),
              ),
              child: const Padding(
                padding: EdgeInsets.symmetric(
                  vertical: 15.0,
                  horizontal: 150.0,
                ),
                child: Text(
                  "Save",
                  style: TextStyle(
                      color: Colors.white, fontSize: 17, fontWeight: FontWeight.w600),
                ),
              ),
            ),
          ),
        ),
      ),
    ],
  ),
)

请注意,您必须在SingleChildScrollView 内放置一个底部填充以考虑该按钮。在您的情况下这很好,因为按钮具有静态高度。但是,如果您需要更花哨的东西,您可能需要按照@Csisanyi 的建议查看How to create a scroll view with fixed footer with Flutter?

【讨论】:

我试过这样做,但问题是页脚中的按钮将部分重叠描述小部件(代码中高度为 400 的绿色容器),我希望描述框滚动过去页脚按钮。 是的,正如我所说,您必须在 SingleChildScrollView 下方设置底部填充。此填充的值应该是底部按钮的高度。 有道理。这应该可以完成这项工作。另一个问题,如果我只希望两个容器滚动怎么办?不是标题。像这样ibb.co/xzzkgtZ 然后在您的堆栈上方,您应该使用包含顶部事物作为其第一个子项和可滚动部分作为第二个子项的列 好的。感谢您的帮助!【参考方案2】:

考虑用Expanded 小部件包装Column

您也可以查看这个颤振文档。它详细解决了这个常见问题。 https://flutter.dev/docs/testing/common-errors

【讨论】:

如果按钮必须位于列的底部,这将是正确的。但是,如果按钮是固定的,则需要一个 Stack,正如我在详细答案中解释的那样。 我明白了。您也可以在这篇文章中查看接受的答案,也许它会有所帮助。 ***.com/questions/54027270/… 我明白了,这更好,因为这里的 cmets 考虑了按钮的底部填充,而我的示例没有【参考方案3】:
Scaffold(
        body: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            Icon(Icons.menu),
                            // Image(), //Asset image

                            Image.asset(
                              'assets/ocean.jpg',
                              height: kToolbarHeight,

                              /// make sure of image height
                              fit: BoxFit.fitHeight,
                            ),
                          ],
                        ),
                        Row(
                          children: <Widget>[
                            const Icon(Icons.notifications_none),
                            const SizedBox(width: 27.0),
                            CircleAvatar(
                              child: Text("JM"),
                            ),
                          ],
                        )
                      ],
                    ),
                    Row(
                      children: const <Widget>[
                        Icon(Icons.arrow_back),
                        SizedBox(width: 20.0),
                        Text("Public page"),
                      ],
                    ),
                    const SizedBox(
                      height: 20.0,
                    ),
                    const Text(
                        "  Please fill the form following the proper order."),
                    const SizedBox(height: 10.0),

                    //todo: OverviewWidget(), //Widget with lots of TextFormField
                    ...List.generate(22, (index) 
                      return TextField(
                        decoration: InputDecoration(hintText: "1st $index"),
                      );
                    ),
                    SizedBox(height: 10.0),
                    //todo: DescriptionWidget(), //Widget with lots of TextFormField
                    ...List.generate(22, (index) 
                      return TextField(
                        decoration: InputDecoration(hintText: "2st $index"),
                      );
                    ),
                  ],
                ),
              ),
              Align(
                alignment: Alignment.bottomCenter,
                child: GestureDetector(
                  onTap: () 
                    print("Hello");
                  ,
                  child: Container(
                    height: 130.0,
                    width: double.infinity,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                      color: Colors.white,
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.shade400,
                          blurRadius: 10,
                          spreadRadius: 1,
                        )
                      ],
                    ),
                    child: Container(
                      margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
                      decoration: BoxDecoration(
                        color: Colors.green.shade400,
                        borderRadius: BorderRadius.circular(35),
                      ),
                      child: const Padding(
                        padding: EdgeInsets.symmetric(
                          vertical: 15.0,
                          horizontal: 150.0,
                        ),
                        child: Text(
                          "Save",
                          style: TextStyle(
                              color: Colors.white,
                              fontSize: 17,
                              fontWeight: FontWeight.w600),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),

【讨论】:

以上是关于ScrollView RenderFlex 溢出 - Flutter的主要内容,如果未能解决你的问题,请参考以下文章

底部溢出 418 像素的 RenderFlex

一个 RenderFlex 在底部溢出了 729 个像素。在 SingleChildScrollView

Flutter Row 小部件通过切断剩余区域解决 RenderFlex 溢出问题

Flutter:如何修复“像素溢出的 RenderFlex”错误?

我收到此错误 A renderFlex 在底部溢出 100 像素

又抛出了一个异常:A RenderFlex 右边溢出了 3.0 像素