例外:-尽管删除了扩展的小部件,但没有布置 RenderBox

Posted

技术标签:

【中文标题】例外:-尽管删除了扩展的小部件,但没有布置 RenderBox【英文标题】:Exception:-RenderBox was not laid out despite removing the expanded widgets 【发布时间】:2021-11-25 08:20:20 【问题描述】:

我正在构建一个带有登录屏幕和注册屏幕的聊天应用程序。验证它(注册和登录)后,您可以开始与其他用户聊天。我在我的 textField 中添加了一个控制器属性,之后我的代码即使在删除控制器后也会崩溃。没有提到错误的行。一旦它开始加载聊天,我就会遇到异常。

我尝试删除 Expanded Widget 并添加 SizedBox 属性而不是它。 我还尝试为我的 ListView 添加 shrinkWrap: true,但没有成功。我无法在这里找到错误。 请帮忙!!

这是错误:-

======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
RenderBox was not laid out: RenderMouseRegion#5a758 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1929 pos 12: 'hasSize'


Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.md

The relevant error-causing widget was: 
  TextField TextField:file:///D:/flashchat1/lib/screens/chat_screen.dart:86:22
When the exception was thrown, this was the stack: 
#2      RenderBox.size (package:flutter/src/rendering/box.dart:1929:12)
#3      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:117:21)
#4      RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#5      ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:56:11)
#6      RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:829:43)
#7      RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:931:32)
#8      RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#9      RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:233:12)
#10     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#11     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#12     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#13     ChildLayoutHelper.layoutChild (package:flutter/src/rendering/layout_helper.dart:56:11)
#14     RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:829:43)
#15     RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:931:32)
#16     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#17     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:233:12)
#18     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#19     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:171:12)
#20     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1097:7)
#21     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:240:7)
#22     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:404:14)
#23     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#24     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#25     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#26     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#27     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1388:11)
#28     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#29     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#30     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#31     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#32     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#33     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#34     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#35     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#36     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#37     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#38     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#39     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#40     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#41     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#42     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#43     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#44     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#45     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3420:14)
#46     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#47     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
#48     RenderObject.layout (package:flutter/src/rendering/object.dart:1858:7)
#49     _RenderTheatre.performLayout (package:flutter/src/widgets/overlay.dart:745:15)
#50     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1713:7)
#51     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:885:18)
#52     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:453:19)
#53     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:883:13)
#54     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
#55     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
#56     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
#57     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5)
#61     _invoke (dart:ui/hooks.dart:166:10)
#62     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5)
#63     _drawFrame (dart:ui/hooks.dart:129:31)
(elided 5 frames from class _AssertionError and dart:async)
The following RenderObject was being processed when the exception was fired: _RenderFocusTrapArea#698c0 relayoutBoundary=up6 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...  parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
...  constraints: BoxConstraints(unconstrained)
...  size: MISSING
RenderObject: _RenderFocusTrapArea#698c0 relayoutBoundary=up6 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
  parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
  constraints: BoxConstraints(unconstrained)
  size: MISSING
...  child: RenderMouseRegion#5a758 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: <none> (can use size)
...    constraints: BoxConstraints(unconstrained)
...    size: MISSING
...    listeners: enter, exit
...    cursor: SystemMouseCursor(text)
...    child: RenderIgnorePointer#e8ea6 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(unconstrained)
...      size: MISSING
...      ignoring: false
...      ignoringSemantics: implicitly false
...      child: RenderSemanticsAnnotations#e40f4 relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(unconstrained)
...        size: MISSING
...        child: RenderPointerListener#bba7b relayoutBoundary=up10 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(unconstrained)
...          size: MISSING
...          behavior: translucent
...          listeners: down
====================================================================================================
I/TetheringManager(10454): registerTetheringEventCallback:com.example.flashchat1
W/DynamiteModule(10454): Local module descriptor class for providerinstaller not found.

这里是代码:-

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flashchat1/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
final _fireStore = FirebaseFirestore.instance;//an instance of fireBase store that stored data created
final _auth = FirebaseAuth.instance;//instance/object of fireBase auth that authorizes users is created
class ChatScreen extends StatefulWidget 
  static String id='Chat_Screen';
  @override
  _ChatScreenState createState() => _ChatScreenState();


class _ChatScreenState extends State<ChatScreen> 
  final messageTextController = TextEditingController();
  late User loggedInUser;//LoggedInUser is of type FireBase user(now changed to user)
  late String messageText;
  @override
  void initState()
  
    super.initState();
    getCurrentUser();//calling the getCurrentUser
  
  void getCurrentUser()
  async
    try
    
      final user= await _auth.currentUser;//get the current user id/name/email.Also currentUser return a future so make it async by adding await and async keywords
      if(user!=null)
      
        loggedInUser=user ;//LoggedInUser = user contains email of the info
        print(loggedInUser.email);
      

    
    catch(e)
    
      print(e);
    
  // Under collection there is documents.Inside documents there are fields like type ,values etc.These fields contain our information
    Future<void> messageStream()//Using a stream it becomes very easy .U just need to click once after you run the app .Then u will be done.
    async //The snapShot here is FireBase's Query SnapShot
      await for(var snapshot in _fireStore.collection('messages').snapshots())//make a variable snapshot to store the entire items of the collection in fireBase (Look at the fireBase console there is a collection called messages).This collection takes the snapshot of all the iteams (not literal snapshot .Think it like a snapShot)
        for(var message in snapshot.docs)//make a variable message to access the snapShot.docs .(docs stands for Documentation.Look at the fireBase console)
        print(message.data());
      
    
  void getMessages()//(The problem with this is that we need to keep clicking on the onPressed button every single time the new message is sent .So it is not convinient
  async 
    final messages = await _fireStore.collection('messages').get();//to retrieve the data from fire base we are creating a variable message
   messages.docs;//retreive the data from document section under the collection in firestore
    for(var message in messages.docs)//since it is a messages.docs is a list we need to loop through it
       
        print(message.data());//print the data its messge.data()
     
  
  Widget build(BuildContext context) 
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
       leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () 
                messageStream();
                //_auth.signOut();
                //Navigator.pop(context);
                //Implement logout functionality
              ),
        ],
        title: Text('⚡️Chat'),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            MessagesStream(),
            Container(
              decoration: kMessageContainerDecoration,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                     TextField(
                      controller:messageTextController,//add a controller to control the textField
                      onChanged: (value) 
                        messageText=value;//Whatever you chat will be stored in the variable String variable messageText
                      ,
                      decoration: kMessageTextFieldDecoration,
                    ),
                  FlatButton(
                    onPressed: () 
                      messageTextController.clear();//clear the text in the TextField as soon as you press the Send button
                      _fireStore.collection('messages').add(
                        'text': messageText,//add the messages sent to fireStore under the messages object that we created manually
                        'Sender': loggedInUser.email,//add the current users email to the sender field
                      ,);
                    ,//goal is to send the data that we type here to the fireStore cloud
                    child: Text(
                      'Send',
                      style: kSendButtonTextStyle,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  


class MessageBubble extends StatelessWidget 
MessageBubble(required this.sender,required this.text);
  final String sender;
  final String text;
  @override
  Widget build(BuildContext context) 
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          Text(sender,
          style:TextStyle(
            fontSize:12.0,
            color:Colors.black54,
          )
          ),
          SizedBox(
            width:200,
            height:50,
            child: Material(
              borderRadius: BorderRadius.circular(20.0),
              elevation: 5.0,
              color:Colors.lightBlueAccent,
              child: Padding(
                padding: const EdgeInsets.symmetric(vertical:10.0,horizontal: 20.0),
                child: Text('$text',
                  style:TextStyle(
                    color:Colors.white,
                    fontSize:15,
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );;
  


class MessagesStream extends StatelessWidget 
  const MessagesStream(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
      stream:_fireStore.collection('messages').snapshots(),
      builder: (context, AsyncSnapshot snapshot) 
        if(!snapshot.hasData)//flutters async snapshot contains a query snapshot
          return Center(
            child:CircularProgressIndicator(
              backgroundColor:Colors.lightBlueAccent,
            ),
          );
        
        final messages = snapshot.data.docs;
        List<MessageBubble> messageBubbles = [];//messageBubbles is of the type MessageBubble
        for(var  message in messages)//Loop through the messages
            
          final messageText = message.data()['text'];//retrieve the data under the text field in message collection
          final messageSender = message.data()['Sender'];//retrieve the data under the Sender field in message collection
          final messageBubble =MessageBubble(sender: messageSender, text: messageText,);
          messageBubbles.add(messageBubble);//add the text to the List messageWidget
        
        return ListView(
            shrinkWrap: true,
            children:messageBubbles,
        );
      ,
    );
  

【问题讨论】:

【参考方案1】:
    我在您的代码中添加了 Expanded,它起作用了。 您可以删除消息流并取消注释我的代码以查看它的外观。 我没有流生成器结果,所以我在你的类中创建了一个静态列表,它的效果很好。
Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          /*Expanded(
            child: ListView.builder(
              itemBuilder: (context, index) => MessageBubble(
                sender: "User1",
                text: "Blah blah blah",
              ),
              shrinkWrap: true,
              itemCount: 10,
            ),
          ),*/
          MessagesStream(),
          Container(
            child: Row(
              children: [
                Expanded(child: Text("Blah blah blah")),
                ElevatedButton(onPressed: () , child: Text("Send"))
              ],
            ),
          )
        ],
      ),
    );
class MessagesStream extends StatelessWidget 
  const MessagesStream(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
      builder: (context, AsyncSnapshot snapshot) 
        final messages = snapshot.data;

        List<MessageBubble> messageBubbles =
            []; //messageBubbles is of the type MessageBubble
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        messageBubbles
            .add(MessageBubble(sender: "user1", text: "Blaah blah blah"));
        return ListView(
          shrinkWrap: true,
          children: messageBubbles,
        );
      ,
    );
  


【讨论】:

我试过这段代码发送按钮没有出现 谢谢我以某种方式想通了。你的回答帮助了很多:)【参考方案2】:

我建议使用bottomNavigationBar 参数来放置您的文本字段和发送按钮,使其始终保持在底部,并用Expanded 包裹您的MessageStream,这样可以占用剩余空间。

如果您在 cmets 部分有任何问题,请让我知道,我很乐意为您提供帮助。

【讨论】:

我尝试将 Exapnded 放在 messageStream 中。它更糟糕的是 :( 。我没有要显示的项目列表来放置底部导航栏。它只是聊天消息。你能告诉我你打算把bottomNavigationBar放在哪里吗?我是Flutter的初学者。 嘿@KarthikKK 你有答案吗,或者我应该分享它吗? 我还没有得到答案。【参考方案3】:

尝试为 MessageStream 添加Expand。因为ListView在渲染的时候需要知道高度。如果你使用Expand,它就会知道渲染的高度是Column的范围。

【讨论】:

以上是关于例外:-尽管删除了扩展的小部件,但没有布置 RenderBox的主要内容,如果未能解决你的问题,请参考以下文章

如何删除 kivy 中的小部件?

无法从 iOS 中删除今日视图扩展

dijit.registry.filter / dijit.registry.map 不会迭代,尽管 dijit.registry 充满了已注册的小部件?

如果未动态添加,如何正确删除Kivy中的小部件

在 Qtabwidget 中扩展小部件

使用 WatchKit 和小部件(今日扩展)保存/删除到 HealthKit?