Robert
Robert

Reputation: 5905

Flutter Listview of items as divider with Listview of items Size problems

I have a working page that is a dynamic listview of messages using a Listview.builder. The itembuilder calls a widget that creates the card. What I am trying to do is change the first list to be a divider that will be a date and then will call a list of items by that date. All the data calls and lists are being created but keep getting hasSize is not true errors and can not see where the size is a problem, I just used the same layouts that were working.

Not sure what code to show to get some assistance, so let me know if you have ideas and what code you might need to see.

This is the start that worked prior to change:

var _children = <Widget>[

  new Expanded(
    child: new RefreshIndicator(
      child: new ListView.builder(
        itemBuilder: _divBuilder,
        itemCount: listcount,
      ),
      onRefresh: _onRefresh,
    ),
  ),
  new Stack(
    alignment: Alignment.centerRight,
    children: <Widget>[
      new TextField(
        decoration: const InputDecoration(
          hintText: 'Chat Reply',
          labelText: 'Chat Reply:',
        ),
        autofocus: false,
        focusNode: _focusnode,
        maxLines: 2,
        controller: _newreplycontroller,
        keyboardType: TextInputType.url,
      ),
      new IconButton(
        icon: new Icon(Icons.send),
        onPressed: _sendReply,
        alignment: Alignment.centerRight,
      )
    ],
  ),
];
return new Scaffold(
  appBar: new AppBar(
    title: mytitle,
    actions: getAppBarActions(context),
  ),
  body: new Column(
    mainAxisSize: MainAxisSize.max,
    children: _children,
  ),
);

Now I have 2 widgets that are being used.

    class MyChatWidget extends StatefulWidget {
  MyChatWidget({Key key, this.datediv, this.msgkey}) : super(key: key);

  final DateTime datediv;
  final String msgkey;

  @override
  _MyChatWidgetState createState() => new _MyChatWidgetState();
}

class _MyChatWidgetState extends State<MyChatWidget> {
  List messagelist;
  int messagecount = 0;
  var jsonCodec = const JsonCodec();

  _getMessages() async {
    var _url = 'http://$baseurl/csapi/messages/getbydate';
    DateChatMessage dcm = new DateChatMessage(widget.msgkey, widget.datediv.toString());
    var json = jsonCodec.encode(dcm);
    var http = createHttpClient();
    var response = await http.post(_url, headers: getAuthHeader(), body: json);

    var messages = await jsonCodec.decode(response.body);

    if (mounted) {
      setState(() {
        messagelist = messages.toList();
        messagecount = messagelist.length;
        //replysub = 'Re: ' + chatlist[0]['sub'];
      });
    }
  }

  @override
  void initState() {
    super.initState();
    //controller = new TabController(length: 4, vsync: this);
    _getMessages();
  }

  @override
  Widget build(BuildContext context) {
    var _children = <Widget>[
      new Divider(height: 5.0,color: Colors.red,),
      new Expanded(
        child: new ListView.builder(
          itemBuilder: _itemBuilder,
          itemCount: messagecount,
        ),
      ),

    ];


    return new Column(
        mainAxisSize: MainAxisSize.min,
        children: _children,
      );
  }

  Widget _itemBuilder(BuildContext context, int index) {
    ChatMessage mychat = getChat(index);
    return new ChatWidget(
      mychat: mychat,
    );
  }

  ChatMessage getChat(int index) {
    //prefs.setInt('pid', myReferralList[index]['pid']);
    return new ChatMessage(
      messagelist[index]['msgkey'],
      messagelist[index]['referralname'],
      messagelist[index]['sub'],
      messagelist[index]['oid'],
      messagelist[index]['oname'],
      messagelist[index]['pid'],
      messagelist[index]['pname'],
      messagelist[index]['sender'],
      messagelist[index]['sendname'],
      messagelist[index]['receiver'],
      messagelist[index]['receivename'],
      messagelist[index]['message'],
      messagelist[index]['submitdate'],
      messagelist[index]['pgrpid'],
      messagelist[index]['prid'],
      messagelist[index]['fcmtoken'],
    );
  }
}


class ChatWidget extends StatefulWidget {
  ChatWidget({Key key, this.mychat}) : super(key: key);

  final ChatMessage mychat;

  @override
  _ChatWidgetState createState() => new _ChatWidgetState();
}

class _ChatWidgetState extends State<ChatWidget> {
  @override
  Widget build(BuildContext context) {
    DateTime submitdate = DateTime.parse(widget.mychat.submitdate).toLocal();

    return new Card(
      child: new Container(
        width: 150.0,
        padding: new EdgeInsets.all(10.0),
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            new Row(
              children: <Widget>[
                new Text(
                  widget.mychat.sendname,
                  style: new TextStyle(
                      fontSize: 15.0, fontWeight: FontWeight.bold),
                ),
                new Text(' @ '),
                new Text(new DateFormat.yMd().add_Hm().format(submitdate)),
                //new Text(submitdate.toLocal().toString())
              ],
            ),

            //new Text(widget.mychat.receivename,style: new TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),),
            //new Text(new DateFormat.yMd().add_Hm().format(submitdate)),
            new Text('${widget.mychat.message}'),
          ],
        ),
      ),
    );
    /*return new ListTile(
      leading: new CircleAvatar(child: new Text(widget.mychat.oname[0])),
      title: new Text(widget.mychat.referralname),
      subtitle: new Text(new DateFormat.yMd().add_Hm().format(submitdate)),
      trailing: new Text(widget.mychat.sendname),
      onTap: _onTap,
    );*/
  }



void _onTap() {
    Route route = new MaterialPageRoute(
      settings: new RouteSettings(name: "/chats/chatconvodetil"),
      builder: (BuildContext context) =>
      new ChatConvoDetail(mychat: widget.mychat),
    );
    Navigator.of(context).push(route);
  }
}

Any guidance would be great


Full Error Stack

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY 

╞═════════════════════════════════════════════════════════
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
When a column is in a parent that does not provide a finite height constraint, for example if it is
in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
space in the vertical direction.
These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child
cannot simultaneously expand to fit its parent.
Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible
themselves to less than the infinite remaining space they would otherwise be forced to take, and
then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum
constraints provided by the parent.
The affected RenderFlex is:
RenderFlex#d88d8 relayoutBoundary=up8 NEEDS-LAYOUT NEEDS-PAINT
The creator information is set to:
Column ← MyChatWidget ← RepaintBoundary-[<0>] ← NotificationListener<KeepAliveNotification> ←
KeepAlive ← AutomaticKeepAlive ← SliverList ← ShrinkWrappingViewport ← _ScrollableScope ←
IgnorePointer-[GlobalKey#ac8f6] ← Listener ← _GestureSemantics ← ⋯
See also: https://flutter.io/layout/
https://flutter.io/debugging/#rendering-layer
http://docs.flutter.io/flutter/rendering/debugDumpRenderTree.html
If none of the above helps enough to fix this problem, please don't hesitate to file a bug:
https://github.com/flutter/flutter/issues/new

When the exception was thrown, this was the stack:

The following RenderObject was being processed when the exception was fired:
RenderFlex#d88d8 relayoutBoundary=up8 NEEDS-LAYOUT NEEDS-PAINT
creator: Column ← MyChatWidget ← RepaintBoundary-[<0>] ←
NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← SliverList ←
ShrinkWrappingViewport ← _ScrollableScope ← IgnorePointer-[GlobalKey#ac8f6] ← Listener ←
_GestureSemantics ← ⋯
size: MISSING
direction: vertical
mainAxisAlignment: start
mainAxisSize: min
crossAxisAlignment: center
verticalDirection: down
RenderConstrainedBox#1d682 relayoutBoundary=up9 NEEDS-PAINT
RenderPositionedBox#d9c42 relayoutBoundary=up10 NEEDS-PAINT
RenderPadding#c357c relayoutBoundary=up11 NEEDS-PAINT
RenderConstrainedBox#3ad51 relayoutBoundary=up12 NEEDS-PAINT
RenderDecoratedBox#e68e0 relayoutBoundary=up13 NEEDS-PAINT
RenderSemanticsGestureHandler#83b48 NEEDS-LAYOUT NEEDS-PAINT
RenderPointerListener#9b129 NEEDS-LAYOUT NEEDS-PAINT
RenderIgnorePointer#aa9c2 NEEDS-LAYOUT NEEDS-PAINT
RenderShrinkWrappingViewport#f658c NEEDS-LAYOUT NEEDS-PAINT
RenderSliverList#7b88e NEEDS-LAYOUT NEEDS-PAINT
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: 'package:flutter/src/rendering/box.dart': Failed assertion: line 1433 pos 12: 'hasSize': is not true.
Another exception was thrown: 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart': Failed assertion: line 455 pos 12: 'child.hasSize': is not true.

Upvotes: 4

Views: 12101

Answers (2)

Shady Aziza
Shady Aziza

Reputation: 53337

'hasSize': is not true is usually related to having a Column or Row with unconstrained size, such that Flutter does not recognize how much space should it render these two widgets in. In your case however, I believe it is caused by your ListView.builder, try to set shrinkWrap property in your ListView.builder to true and see if it solves your problem, otherwise it is caused by a Column or a Row. But I suppose setting shrinkWrap:true should solve it, so try it first.

After going into further details about the error, it seemed that changing Expanded to Flexible have fixed the issue.

Upvotes: 7

Arnold Parge
Arnold Parge

Reputation: 6867

Use Flexible instead of Expanded.

Upvotes: 0

Related Questions