You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter组件布局异常:打开‘添加书籍’页面出现白屏无文本框

问题分析:Flutter添加书籍窗口白屏与布局错误

问题现象

  • 打开“添加书籍”窗口时出现白屏,无法看到文本框,仅显示空白页面
  • 控制台抛出以下错误信息:

NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
RenderRepaintBoundary#5e192 relayoutBoundary=up1 NEEDS-PAINT
Failed assertion: line 1785 pos 12: 'hasSize'
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Cannot hit test a render box that has never been laid out.

相关Build方法代码

@override Widget build(BuildContext context) { 
  return Scaffold( 
    //resizeToAvoidBottomPadding: false, 
    appBar: AppBar(title: Text("Add book")), 
    body: Container( 
      child: Form( 
        key: _formKey, 
        child: Column( 
          children: [ 
            Expanded( 
              child: SingleChildScrollView( 
                child: Column( 
                  children: <Widget>[ 
                    // Book name 
                    Padding( 
                      padding: EdgeInsets.all(20.0), 
                      child: Container( 
                        //height: 30, 
                        decoration: BoxDecoration( 
                          borderRadius: BorderRadius.all(Radius.circular(20)), 
                        ), 
                        //alignment: Alignment.center, 
                        child: Container( 
                          padding: const EdgeInsets.only( 
                            top: 10, bottom: 10, left: 20, right: 20), 
                          decoration: new BoxDecoration( 
                            color: Color(0x70487bea), 
                            borderRadius: new BorderRadius.all(Radius.circular(30))), 
                          child: TextFormField( 
                            controller: nameController, 
                            decoration: InputDecoration( 
                              border: InputBorder.none, 
                              hintText: " Write name", 
                              hintStyle: TextStyle(color: Colors.grey[900]), 
                            ), 
                          ), 
                        ), 
                      ), 
                    ), 
                    // Author 
                    Padding( 
                      padding: EdgeInsets.all(20.0), 
                      child: Container( 
                        decoration: BoxDecoration( 
                          borderRadius: BorderRadius.all(Radius.circular(20)), 
                        ), 
                        //alignment: Alignment.center, 
                        child: Container( 
                          padding: const EdgeInsets.only( 
                            top: 10, bottom: 10, left: 20, right: 20), 
                          decoration: new BoxDecoration( 
                            color: Color(0x70487bea), 
                            borderRadius: new BorderRadius.all(Radius.circular(30))), 
                          child: TextFormField( 
                            controller: authorController, 
                            decoration: InputDecoration( 
                              border: InputBorder.none, 
                              hintText: " Write name", 
                              hintStyle: TextStyle(color: Colors.grey[900]), 
                            ), 
                          ), 
                        ), 
                      ), 
                    ), 
                    // Category 
                    Padding( 
                      padding: EdgeInsets.all(20.0), 
                      child: DropdownButtonFormField( 
                        value: dropdownValue, 
                        icon: Icon(Icons.arrow_downward), 
                        decoration: InputDecoration( 
                          labelText: "Choose category", 
                          enabledBorder: OutlineInputBorder( 
                            borderRadius: BorderRadius.circular(10.0), 
                          ), 
                        ), 
                        //alignment: Alignment.center, 
                        items: listOfCategories.map((String value) { 
                          return new DropdownMenuItem<String>( 
                            value: value, 
                            child: new Text(value), 
                          ); 
                        }).toList(), 
                        onChanged: (String newValue) { 
                          setState(() { 
                            dropdownValue = newValue; 
                          }); 
                        }, 
                      ), 
                    ), 
                    //temp placement 
                    // Submit 
                    Flexible( 
                      child: Padding( 
                        padding: EdgeInsets.all(20.0), 
                        child: isLoading ? CircularProgressIndicator() : Container( 
                          alignment: Alignment.center, 
                          width: MediaQuery.of(context).size.width, 
                          padding: EdgeInsets.symmetric(vertical: 10), 
                          child: RaisedButton( 
                            onPressed: () { 
                              if (_formKey.currentState.validate()) { 
                                setState(() { 
                                  isLoading = true; 
                                }); 
                                //getUsername(); 
                                addToFb(); 
                                //dispose(); 
                              } 
                            }, 
                            shape: RoundedRectangleBorder( 
                              borderRadius: BorderRadius.circular(30), 
                              side: BorderSide(color: Colors.indigo[500])), 
                            color: Colors.indigo[400], 
                            child: Text( 
                              "Save", 
                              style: TextStyle( 
                                fontSize: 16.0, color: Colors.white), 
                            ), 
                            padding: EdgeInsets.fromLTRB(35, 15, 35, 15), 
                          ), 
                        ), 
                      ), 
                    ) 
                  ], 
                ), 
              ), 
            ), 
          ], 
        ), 
      ), 
    ), 
  ); 
}

问题根源分析

我帮你梳理下,你遇到的白屏和布局错误,核心是布局层级的尺寸约束搞混了,具体有这几个坑:

  1. Expanded和SingleChildScrollView的搭配错了

    • Expanded的作用是把父组件剩下的空间全占了,但SingleChildScrollView是靠子内容来撑大小的,你把它俩套一起,就会让SingleChildScrollView试图无限扩张,里面的Column根本算不出自己该多大,直接触发了'hasSize'的断言失败——这就是白屏的主要原因。
  2. 提交按钮外面的Flexible完全没必要

    • SingleChildScrollView里的组件不需要用Flexible来分配空间,这玩意儿在滚动视图里根本起不了作用,反而会干扰Flutter的布局计算,导致渲染框连布局都完成不了,自然就报“无法点击未布局的渲染框”的错误了。
  3. 文本框的容器没给明确尺寸

    • 你套了好几层Container,但外层的都没设高度,Flutter不知道这些容器该多大,也会让布局计算乱套。

修复方案

按照这几步调整代码,问题应该就能解决:

  1. 删掉多余的Expanded和Flexible

    • 把body里包着SingleChildScrollView的Expanded去掉,直接让滚动视图作为Form的子组件就行,滚动视图本身会自适应内容高度,不需要硬拉它占满空间。
    • 提交按钮外面的Flexible也删掉,让按钮自己该多大就多大。
  2. 简化容器嵌套,给文本框容器加个明确高度

    • 你原来文本框套了两层Container,可以合并成一层,同时给这个容器设个高度(比如50),这样Flutter就能明确知道文本框区域的大小,不会再乱计算。

调整后的代码示例

@override Widget build(BuildContext context) { 
  return Scaffold( 
    appBar: AppBar(title: Text("Add book")), 
    body: Container( 
      padding: EdgeInsets.symmetric(horizontal: 16),
      child: Form( 
        key: _formKey, 
        child: SingleChildScrollView( 
          padding: EdgeInsets.symmetric(vertical: 20), 
          child: Column( 
            children: <Widget>[ 
              // Book name 
              Padding( 
                padding: EdgeInsets.only(bottom: 20.0), 
                child: Container( 
                  height: 50,
                  decoration: BoxDecoration( 
                    color: Color(0x70487bea), 
                    borderRadius: BorderRadius.all(Radius.circular(30)) 
                  ), 
                  child: Padding( 
                    padding: const EdgeInsets.symmetric(horizontal: 20), 
                    child: TextFormField( 
                      controller: nameController, 
                      decoration: InputDecoration( 
                        border: InputBorder.none, 
                        hintText: " Write book name", 
                        hintStyle: TextStyle(color: Colors.grey[900]), 
                      ), 
                    ), 
                  ), 
                ), 
              ), 
              // Author 
              Padding( 
                padding: EdgeInsets.only(bottom: 20.0), 
                child: Container( 
                  height: 50, 
                  decoration: BoxDecoration( 
                    color: Color(0x70487bea), 
                    borderRadius: BorderRadius.all(Radius.circular(30)) 
                  ), 
                  child: Padding( 
                    padding: const EdgeInsets.symmetric(horizontal: 20), 
                    child: TextFormField( 
                      controller: authorController, 
                      decoration: InputDecoration( 
                        border: InputBorder.none, 
                        hintText: " Write author name", 
                        hintStyle: TextStyle(color: Colors.grey[900]), 
                      ), 
                    ), 
                  ), 
                ), 
              ), 
              // Category 
              Padding( 
                padding: EdgeInsets.only(bottom: 20.0), 
                child: DropdownButtonFormField( 
                  value: dropdownValue, 
                  icon: Icon(Icons.arrow_downward), 
                  decoration: InputDecoration( 
                    labelText: "Choose category", 
                    enabledBorder: OutlineInputBorder( 
                      borderRadius: BorderRadius.circular(10.0), 
                    ), 
                  ), 
                  items: listOfCategories.map((String value) { 
                    return DropdownMenuItem<String>( 
                      value: value, 
                      child: Text(value), 
                    ); 
                  }).toList(), 
                  onChanged: (String newValue) { 
                    setState(() { 
                      dropdownValue = newValue; 
                    }); 
                  }, 
                ), 
              ), 
              // Submit 
              Padding( 
                padding: EdgeInsets.all(20.0), 
                child: isLoading ? CircularProgressIndicator() : Container( 
                  width: double.infinity, 
                  child: RaisedButton( 
                    onPressed: () { 
                      if (_formKey.currentState.validate()) { 
                        setState(() { 
                          isLoading = true; 
                        }); 
                        addToFb(); 
                      } 
                    }, 
                    shape: RoundedRectangleBorder( 
                      borderRadius: BorderRadius.circular(30), 
                      side: BorderSide(color: Colors.indigo[500])), 
                    color: Colors.indigo[400], 
                    child: Text( 
                      "Save", 
                      style: TextStyle( 
                        fontSize: 16.0, color: Colors.white), 
                    ), 
                    padding: EdgeInsets.fromLTRB(35, 15, 35, 15), 
                  ), 
                ), 
              ), 
            ], 
          ), 
        ), 
      ), 
    ), 
  ); 
}

内容的提问来源于stack exchange,提问作者Chorche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:57:52