问:
Flutter Listview in a Listview scrolling weirdness
So I have a listview.builder that uses an itembuilder that calls another Listview.builder and another itembuilder.  I got help on another thread for some sizing issues and everything presents great.  The goal of the page is to have a date divider that then has a list of messages by that date, this can grow based on messages for the day and current day.  However there is some weirdness to the scolling, if you grab the divider it scrolls fine up and down, however if you hot one of the cards between the divider it only scrolls within that area. Wondered if there was a better way to accomplish the same layout result.

Any help would be great.  I put all the code form the page here and let me know if you have questions.  Again it all works good and layout is exactly what I want, just scrolls weird and not really effective.

```<code>import 'dart:async';
import 'dart:convert';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cswauthapp/models.dart';
import 'package:cswauthapp/ChatConvoDetail.dart';
import 'package:cswauthapp/Settings.dart' as Admin;
import 'package:cswauthapp/HomePage.dart' as HomePage;
import 'package:cswauthapp/main.dart' as MyHomePage;
import 'package:cswauthapp/PostAuthHome.dart' as PostAuthHome;

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

  static const String routeName = "/ChatNTDate";

  final ChatList mychat;
  final String title;

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

/// // 1. After the page has been created, register it with the app routes
/// routes: <String, WidgetBuilder>{
///   ChatNoThread.routeName: (BuildContext context) => new ChatNoThread(title: "ChatNoThread"),
/// },
///
/// // 2. Then this could be used to navigate to the page.
/// Navigator.pushNamed(context, ChatNoThread.routeName);
///

class _ChatNTDateSepState extends State<ChatNTDateSep> {
  SharedPreferences prefs;
  int oid = 0;
  int pid = 0;
  int authlevel = 0;
  bool admin = false;
  int type = 0;
  String msgid = '';
  List chatlist;
  int listcount = 0;
  bool grpmsg = true;
  String sender = '';
  String receiver = '';
  String message = '';
  String oname = '';
  String pname = '';
  String sendname;
  String receivename;
  String replyto = '';
  String replyfrom = '';
  String replysub = '';
  final TextEditingController _newreplycontroller = new TextEditingController();
  String myfcmtoken = 'NONE';

  _getPrefs() async {
    prefs = await SharedPreferences.getInstance();
    //hasRef = prefs.getBool('hasRef');

    if (mounted) {
      setState(() {
        oid = prefs.getInt('oid');
        pid = prefs.getInt('pid');
        authlevel = prefs.getInt('authlevel');
        admin = prefs.getBool('admin');
        type = 1;
        msgid = widget.mychat.msgkey;
        if (widget.mychat.grpid == '0') {
          grpmsg = false;
        } else {
          grpmsg = true;
        }
        oname = widget.mychat.oname;
        pname = widget.mychat.pname;
        myfcmtoken = prefs.getString('fcmtoken');
        if (authlevel == 0) {
          sender = 'o';
          receiver = 'p';
          sendname = widget.mychat.oname;
          receivename = widget.mychat.pname;
        } else {
          sender = 'p';
          receiver = 'o';
          sendname = widget.mychat.pname;
          receivename = widget.mychat.oname;
        }
        _getChats();
      });
    }
  }

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

  var jsonCodec = const JsonCodec();
  var _focusnode = new FocusNode();

  _getChats() async {
    //var _url = 'http://$baseurl/csapi/getmessages/$type/$msgid';
    var _url = 'http://$baseurl/csapi/messages/getdates/$msgid';

    var http = createHttpClient();
    var response = await http.get(_url, headers: getAuthHeader());

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

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

  Future<Null> _onRefresh() {
    Completer<Null> completer = new Completer<Null>();
    Timer timer = new Timer(new Duration(seconds: 1), () {
      _getChats();
      completer.complete();
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {

    Widget mytitle;
    if (grpmsg) {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.people),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    } else {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.person),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    }

    /*Widget _grpHdr() {
      assert(grpmsg);
      return new Text(
        widget.mychat.referralname,
        style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
      );
    }

    Widget _noGrpHdr() {
      assert(!grpmsg);
      return new Text(
        widget.mychat.referralname,
        style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
      );
    }*/

    var _children = <Widget>[

      new Expanded(
        child: new RefreshIndicator(
          child: new ListView.builder(
            itemBuilder: _divBuilder,
            itemCount: listcount,shrinkWrap: true,
          ),
          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.min,
          children: _children,
        ),
    );
  }

  Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    );

  }

  DateTime getDateDiv(int index) {
    DateTime msgdate = DateTime.parse(chatlist[index]['chatdate']).toLocal();
    return msgdate;
  }

  _sendReply() {
    if (_newreplycontroller.text.isEmpty) {
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
            /*new FlatButton(
              child: const Text('SHOW'),
              onPressed: () {
                Navigator.pop(context, true);
              }),*/
          ],
        ),
      );
    } else {

      DateTime dateSubmit = new DateTime.now();
      var mymessage = _newreplycontroller.text;
      ChatMessage mychat = new ChatMessage(
          widget.mychat.msgkey,
          widget.mychat.referralname,
          replysub,
          oid,
          oname,
          pid,
          pname,
          sender,
          sendname,
          receiver,
          receivename,
          mymessage,
          dateSubmit.toString(),
          widget.mychat.grpid,
          widget.mychat.prid,
          myfcmtoken);
      _doSendReply(mychat);
    }
  }

  _doSendReply(mychat) async {

    var json = jsonCodec.encode(mychat);
    var _url = 'http://$baseurl/csapi/sendchatmsg';

    var http = createHttpClient();
    var response = await http.post(_url, body: json, headers: getJSONHeader());

    var chatresp = await jsonCodec.decode(response.body);
    if (chatresp.contains('GOOD')) {
      _getChats();
      _newreplycontroller.text = '';
      _focusnode.unfocus();
      /*Route route = new MaterialPageRoute(
        settings: new RouteSettings(name: "/Chat"),
        builder: (BuildContext context) => new Chat.Chat(title: "Loop Chat Reply"),
      );
      Navigator.of(context).push(route);*/
    } else if (chatresp.contains('EMPTY')){
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
            /*new FlatButton(
              child: const Text('SHOW'),
              onPressed: () {
                Navigator.pop(context, true);
              }),*/
          ],
        ),
      );
    } else {}

  }
}

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();
  var mydate = '';

  _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;
        if (new DateFormat.yMd().format(widget.datediv) == new DateFormat.yMd().format(new DateTime.now())) {
          mydate = 'Today';
        } else {
          mydate = new DateFormat.yMMMEd().format(widget.datediv);
        }
        //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 Text(mydate, textAlign: TextAlign.left,),
      new Divider(
        height: 5.0,
        color: Colors.grey,
      ),
      //new Text(new DateFormat.yMd().format(widget.datediv),),

      new ListView.builder(
        itemBuilder: _itemBuilder,
        itemCount: messagecount,
        shrinkWrap: true,
      ),

      /*new Flexible(
        child: new ListView.builder(
          itemBuilder: _itemBuilder,
          itemCount: messagecount,
          shrinkWrap: true,
        ),
      ),*/

    ];

    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(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                new Text(
                  widget.mychat.sendname,
                  style: new TextStyle(
                      fontSize: 15.0, fontWeight: FontWeight.bold),
                ),
                new Text(' '),
                new Text(new DateFormat.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,
    );*/
  }
}
</code>```

Here is the latest UPDATED CODE:

```<code>import 'dart:async';
import 'dart:convert';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cswauthapp/models.dart';
import 'package:cswauthapp/ChatConvoDetail.dart';
import 'package:cswauthapp/Settings.dart' as Admin;
import 'package:cswauthapp/HomePage.dart' as HomePage;
import 'package:cswauthapp/main.dart' as MyHomePage;
import 'package:cswauthapp/PostAuthHome.dart' as PostAuthHome;

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

  static const String routeName = "/ChatDivided";

  final ChatList mychat;
  final String title;

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

class _ChatDividedState extends State<ChatDivided> {
  SharedPreferences prefs;
  int oid = 0;
  int pid = 0;
  int authlevel = 0;
  bool admin = false;
  int type = 0;
  String msgid = '';
  List chatlist;
  int listcount = 0;
  bool grpmsg = true;
  String sender = '';
  String receiver = '';
  String message = '';
  String oname = '';
  String pname = '';
  String sendname;
  String receivename;
  String replyto = '';
  String replyfrom = '';
  String replysub = '';
  final TextEditingController _newreplycontroller = new TextEditingController();
  String myfcmtoken = 'NONE';

  _getPrefs() async {
    prefs = await SharedPreferences.getInstance();
    //hasRef = prefs.getBool('hasRef');

    if (mounted) {
      setState(() {
        oid = prefs.getInt('oid');
        pid = prefs.getInt('pid');
        authlevel = prefs.getInt('authlevel');
        admin = prefs.getBool('admin');
        type = 1;
        msgid = widget.mychat.msgkey;
        if (widget.mychat.grpid == '0') {
          grpmsg = false;
        } else {
          grpmsg = true;
        }
        oname = widget.mychat.oname;
        pname = widget.mychat.pname;
        myfcmtoken = prefs.getString('fcmtoken');
        if (authlevel == 0) {
          sender = 'o';
          receiver = 'p';
          sendname = widget.mychat.oname;
          receivename = widget.mychat.pname;
        } else {
          sender = 'p';
          receiver = 'o';
          sendname = widget.mychat.pname;
          receivename = widget.mychat.oname;
        }
        _getChats();
      });
    }
  }

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

  var jsonCodec = const JsonCodec();
  var _focusnode = new FocusNode();

  _getChats() async {
    //var _url = 'http://$baseurl/csapi/getmessages/$type/$msgid';
    var _url = 'http://$baseurl/csapi/messages/getdates/$msgid';

    var http = createHttpClient();
    var response = await http.get(_url, headers: getAuthHeader());

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

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

  Future<Null> _onRefresh() {
    Completer<Null> completer = new Completer<Null>();
    Timer timer = new Timer(new Duration(seconds: 1), () {
      _getChats();
      completer.complete();
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {

    Widget mytitle;
    if (grpmsg) {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.people),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    } else {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.person),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    }

    return new Scaffold(
      appBar: new AppBar(
        title: mytitle,
        actions: getAppBarActions(context),
      ),
      body: new Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          new Expanded(
            child: new RefreshIndicator(
              child: new ListView.builder(
                itemBuilder: _divBuilder,
                itemCount: listcount,shrinkWrap: true,
              ),
              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,
              )
            ],
          ),
        ],
      ),
    );
  }

  Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    );

  }

  DateTime getDateDiv(int index) {
    DateTime msgdate = DateTime.parse(chatlist[index]['chatdate']).toLocal();
    return msgdate;
  }

  _sendReply() {
    if (_newreplycontroller.text.isEmpty) {
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
          ],
        ),
      );
    } else {

      DateTime dateSubmit = new DateTime.now();
      var mymessage = _newreplycontroller.text;
      ChatMessage mychat = new ChatMessage(
          widget.mychat.msgkey,
          widget.mychat.referralname,
          replysub,
          oid,
          oname,
          pid,
          pname,
          sender,
          sendname,
          receiver,
          receivename,
          mymessage,
          dateSubmit.toString(),
          widget.mychat.grpid,
          widget.mychat.prid,
          myfcmtoken);
      _doSendReply(mychat);
    }
  }

  _doSendReply(mychat) async {

    var json = jsonCodec.encode(mychat);
    var _url = 'http://$baseurl/csapi/sendchatmsg';

    var http = createHttpClient();
    var response = await http.post(_url, body: json, headers: getJSONHeader());

    var chatresp = await jsonCodec.decode(response.body);
    if (chatresp.contains('GOOD')) {
      _getChats();
      _newreplycontroller.text = '';
      _focusnode.unfocus();

    } else if (chatresp.contains('EMPTY')){
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),

          ],
        ),
      );
    } else {}

  }
}

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();
  var mydate = '';

  _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;
        if (new DateFormat.yMd().format(widget.datediv) == new DateFormat.yMd().format(new DateTime.now())) {
          mydate = 'Today';
        } else {
          mydate = new DateFormat.yMMMEd().format(widget.datediv);
        }
        //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 = [
      new Text(mydate, textAlign: TextAlign.left,),
      new Divider(
        height: 5.0,
        color: Colors.grey,
      ),

      new Flexible(
          child: new Column(
            children: new List.generate(messagecount, (int index) {

              ChatMessage mychat = getChat(index);
              DateTime submitdate = DateTime.parse(mychat.submitdate).toLocal();
              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(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          new Text(
                            mychat.sendname,
                            style: new TextStyle(
                                fontSize: 15.0, fontWeight: FontWeight.bold),
                          ),
                          new Text(' '),
                          new Text(new DateFormat.Hm().format(submitdate)),

                        ],
                      ),

                      new Text('${mychat.message}'),
                    ],
                  ),
                ),
              );
            }
            ),
          ),
      ),

    ];

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

  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'],
    );
  }
}
</code>```

答:
You would save yourself so much trouble if you can build your date divider inside your ChatWidget build:

```<code>import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Column(

      children: <Widget>[

        new Flexible (child: new ListView.builder(
            shrinkWrap: true,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return new ChatWidget (

              );
            })),
        new Stack(
          alignment: Alignment.centerRight,
          children: <Widget>[
            new TextField(
              decoration: const InputDecoration(
                hintText: 'Chat Reply',
                labelText: 'Chat Reply:',
              ),
              autofocus: false,
              maxLines: 2,
              keyboardType: TextInputType.url,
            ),
            new IconButton(
              icon: new Icon(Icons.send),
              onPressed: null,
              alignment: Alignment.centerRight,
            )
          ],
        ),
      ],
    ));
  }
}

class ChatWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container (child: new Column (children: <Widget>[

      new Divider(height: 15.0, color: Colors.red),
      new Text("My Awesome Date"),
      new Divider(height: 15.0, color: Colors.red),

      new Column(
        children: <Widget>[
          new Card(
              child: new Container(
                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(
                          "Awesome Child",
                          style: new TextStyle(
                              fontSize: 15.0, fontWeight: FontWeight.bold),
                        ),
                        new Text(' @ '),
                        new Text("Awesome Date"),
                      ],
                    ),

                    new Text(
                        'AWESOMMMMMMMMMMMMMMMMMMMMMMMMMMEEEEEEEEEEEEEEEEEEEEEEEEEEE'),
                  ],
                ),
              ))
        ],
      )

    ],),
    );
  }
}
</code>```

Edit

Try this:

```<code>    Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new Column(children: <Widget>[new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    ),
    ],);
  }
</code>```

Update

Generate a list of cards based on the number of message for each divider like this:

```<code>return new Column(
      children: new List.generate(
          5, (int index) { //5 = number of cards per date
        return new Card(
          //layout design
        );
      }),
    );
</code>```

Update
This is a full example of what I meant on List.generate:

```<code>import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Column(

      children: <Widget>[

        new Flexible (child: new ListView.builder(
            shrinkWrap: true,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return new Column(
                children: <Widget>[
                  new Divider(color: Colors.red,),
                  new Text("Date$index"),
                  new ChatWidget(
                    //pass the number of messages for date[index]
                  )
                ],
              );
            })),
        new Stack(
          alignment: Alignment.centerRight,
          children: <Widget>[
            new TextField(
              decoration: const InputDecoration(
                hintText: 'Chat Reply',
                labelText: 'Chat Reply:',
              ),
              autofocus: false,
              maxLines: 2,
              keyboardType: TextInputType.url,
            ),
            new IconButton(
              icon: new Icon(Icons.send),
              onPressed: null,
              alignment: Alignment.centerRight,
            )
          ],
        ),
      ],
    ));
  }
}

class ChatWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Column(
      children: new List.generate(
          5, (int index) { //5 = number of messages of the current dat[index]
        return new Card(
          //layout design
          child: new Text("Message$index"),
        );
      }),
    );
  }
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
So I have a listview.builder that uses an itembuilder that calls another Listview.builder and another itembuilder.  I got help on another thread for some sizing issues and everything presents great.  The goal of the page is to have a date divider that then has a list of messages by that date, this can grow based on messages for the day and current day.  However there is some weirdness to the scolling, if you grab the divider it scrolls fine up and down, however if you hot one of the cards between the divider it only scrolls within that area. Wondered if there was a better way to accomplish the same layout result.

Any help would be great.  I put all the code form the page here and let me know if you have questions.  Again it all works good and layout is exactly what I want, just scrolls weird and not really effective.

import 'dart:async';
import 'dart:convert';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cswauthapp/models.dart';
import 'package:cswauthapp/ChatConvoDetail.dart';
import 'package:cswauthapp/Settings.dart' as Admin;
import 'package:cswauthapp/HomePage.dart' as HomePage;
import 'package:cswauthapp/main.dart' as MyHomePage;
import 'package:cswauthapp/PostAuthHome.dart' as PostAuthHome;

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

  static const String routeName = "/ChatNTDate";

  final ChatList mychat;
  final String title;

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

/// // 1. After the page has been created, register it with the app routes
/// routes: <String, WidgetBuilder>{
///   ChatNoThread.routeName: (BuildContext context) => new ChatNoThread(title: "ChatNoThread"),
/// },
///
/// // 2. Then this could be used to navigate to the page.
/// Navigator.pushNamed(context, ChatNoThread.routeName);
///

class _ChatNTDateSepState extends State<ChatNTDateSep> {
  SharedPreferences prefs;
  int oid = 0;
  int pid = 0;
  int authlevel = 0;
  bool admin = false;
  int type = 0;
  String msgid = '';
  List chatlist;
  int listcount = 0;
  bool grpmsg = true;
  String sender = '';
  String receiver = '';
  String message = '';
  String oname = '';
  String pname = '';
  String sendname;
  String receivename;
  String replyto = '';
  String replyfrom = '';
  String replysub = '';
  final TextEditingController _newreplycontroller = new TextEditingController();
  String myfcmtoken = 'NONE';

  _getPrefs() async {
    prefs = await SharedPreferences.getInstance();
    //hasRef = prefs.getBool('hasRef');

    if (mounted) {
      setState(() {
        oid = prefs.getInt('oid');
        pid = prefs.getInt('pid');
        authlevel = prefs.getInt('authlevel');
        admin = prefs.getBool('admin');
        type = 1;
        msgid = widget.mychat.msgkey;
        if (widget.mychat.grpid == '0') {
          grpmsg = false;
        } else {
          grpmsg = true;
        }
        oname = widget.mychat.oname;
        pname = widget.mychat.pname;
        myfcmtoken = prefs.getString('fcmtoken');
        if (authlevel == 0) {
          sender = 'o';
          receiver = 'p';
          sendname = widget.mychat.oname;
          receivename = widget.mychat.pname;
        } else {
          sender = 'p';
          receiver = 'o';
          sendname = widget.mychat.pname;
          receivename = widget.mychat.oname;
        }
        _getChats();
      });
    }
  }

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

  var jsonCodec = const JsonCodec();
  var _focusnode = new FocusNode();

  _getChats() async {
    //var _url = 'http://$baseurl/csapi/getmessages/$type/$msgid';
    var _url = 'http://$baseurl/csapi/messages/getdates/$msgid';

    var http = createHttpClient();
    var response = await http.get(_url, headers: getAuthHeader());

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

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

  Future<Null> _onRefresh() {
    Completer<Null> completer = new Completer<Null>();
    Timer timer = new Timer(new Duration(seconds: 1), () {
      _getChats();
      completer.complete();
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {

    Widget mytitle;
    if (grpmsg) {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.people),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    } else {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.person),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    }

    /*Widget _grpHdr() {
      assert(grpmsg);
      return new Text(
        widget.mychat.referralname,
        style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
      );
    }

    Widget _noGrpHdr() {
      assert(!grpmsg);
      return new Text(
        widget.mychat.referralname,
        style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
      );
    }*/

    var _children = <Widget>[

      new Expanded(
        child: new RefreshIndicator(
          child: new ListView.builder(
            itemBuilder: _divBuilder,
            itemCount: listcount,shrinkWrap: true,
          ),
          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.min,
          children: _children,
        ),
    );
  }

  Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    );

  }

  DateTime getDateDiv(int index) {
    DateTime msgdate = DateTime.parse(chatlist[index]['chatdate']).toLocal();
    return msgdate;
  }

  _sendReply() {
    if (_newreplycontroller.text.isEmpty) {
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
            /*new FlatButton(
              child: const Text('SHOW'),
              onPressed: () {
                Navigator.pop(context, true);
              }),*/
          ],
        ),
      );
    } else {

      DateTime dateSubmit = new DateTime.now();
      var mymessage = _newreplycontroller.text;
      ChatMessage mychat = new ChatMessage(
          widget.mychat.msgkey,
          widget.mychat.referralname,
          replysub,
          oid,
          oname,
          pid,
          pname,
          sender,
          sendname,
          receiver,
          receivename,
          mymessage,
          dateSubmit.toString(),
          widget.mychat.grpid,
          widget.mychat.prid,
          myfcmtoken);
      _doSendReply(mychat);
    }
  }

  _doSendReply(mychat) async {

    var json = jsonCodec.encode(mychat);
    var _url = 'http://$baseurl/csapi/sendchatmsg';

    var http = createHttpClient();
    var response = await http.post(_url, body: json, headers: getJSONHeader());

    var chatresp = await jsonCodec.decode(response.body);
    if (chatresp.contains('GOOD')) {
      _getChats();
      _newreplycontroller.text = '';
      _focusnode.unfocus();
      /*Route route = new MaterialPageRoute(
        settings: new RouteSettings(name: "/Chat"),
        builder: (BuildContext context) => new Chat.Chat(title: "Loop Chat Reply"),
      );
      Navigator.of(context).push(route);*/
    } else if (chatresp.contains('EMPTY')){
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
            /*new FlatButton(
              child: const Text('SHOW'),
              onPressed: () {
                Navigator.pop(context, true);
              }),*/
          ],
        ),
      );
    } else {}

  }
}

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();
  var mydate = '';

  _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;
        if (new DateFormat.yMd().format(widget.datediv) == new DateFormat.yMd().format(new DateTime.now())) {
          mydate = 'Today';
        } else {
          mydate = new DateFormat.yMMMEd().format(widget.datediv);
        }
        //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 Text(mydate, textAlign: TextAlign.left,),
      new Divider(
        height: 5.0,
        color: Colors.grey,
      ),
      //new Text(new DateFormat.yMd().format(widget.datediv),),

      new ListView.builder(
        itemBuilder: _itemBuilder,
        itemCount: messagecount,
        shrinkWrap: true,
      ),

      /*new Flexible(
        child: new ListView.builder(
          itemBuilder: _itemBuilder,
          itemCount: messagecount,
          shrinkWrap: true,
        ),
      ),*/

    ];

    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(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                new Text(
                  widget.mychat.sendname,
                  style: new TextStyle(
                      fontSize: 15.0, fontWeight: FontWeight.bold),
                ),
                new Text(' '),
                new Text(new DateFormat.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,
    );*/
  }
}

Here is the latest UPDATED CODE:

import 'dart:async';
import 'dart:convert';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cswauthapp/models.dart';
import 'package:cswauthapp/ChatConvoDetail.dart';
import 'package:cswauthapp/Settings.dart' as Admin;
import 'package:cswauthapp/HomePage.dart' as HomePage;
import 'package:cswauthapp/main.dart' as MyHomePage;
import 'package:cswauthapp/PostAuthHome.dart' as PostAuthHome;

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

  static const String routeName = "/ChatDivided";

  final ChatList mychat;
  final String title;

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

class _ChatDividedState extends State<ChatDivided> {
  SharedPreferences prefs;
  int oid = 0;
  int pid = 0;
  int authlevel = 0;
  bool admin = false;
  int type = 0;
  String msgid = '';
  List chatlist;
  int listcount = 0;
  bool grpmsg = true;
  String sender = '';
  String receiver = '';
  String message = '';
  String oname = '';
  String pname = '';
  String sendname;
  String receivename;
  String replyto = '';
  String replyfrom = '';
  String replysub = '';
  final TextEditingController _newreplycontroller = new TextEditingController();
  String myfcmtoken = 'NONE';

  _getPrefs() async {
    prefs = await SharedPreferences.getInstance();
    //hasRef = prefs.getBool('hasRef');

    if (mounted) {
      setState(() {
        oid = prefs.getInt('oid');
        pid = prefs.getInt('pid');
        authlevel = prefs.getInt('authlevel');
        admin = prefs.getBool('admin');
        type = 1;
        msgid = widget.mychat.msgkey;
        if (widget.mychat.grpid == '0') {
          grpmsg = false;
        } else {
          grpmsg = true;
        }
        oname = widget.mychat.oname;
        pname = widget.mychat.pname;
        myfcmtoken = prefs.getString('fcmtoken');
        if (authlevel == 0) {
          sender = 'o';
          receiver = 'p';
          sendname = widget.mychat.oname;
          receivename = widget.mychat.pname;
        } else {
          sender = 'p';
          receiver = 'o';
          sendname = widget.mychat.pname;
          receivename = widget.mychat.oname;
        }
        _getChats();
      });
    }
  }

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

  var jsonCodec = const JsonCodec();
  var _focusnode = new FocusNode();

  _getChats() async {
    //var _url = 'http://$baseurl/csapi/getmessages/$type/$msgid';
    var _url = 'http://$baseurl/csapi/messages/getdates/$msgid';

    var http = createHttpClient();
    var response = await http.get(_url, headers: getAuthHeader());

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

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

  Future<Null> _onRefresh() {
    Completer<Null> completer = new Completer<Null>();
    Timer timer = new Timer(new Duration(seconds: 1), () {
      _getChats();
      completer.complete();
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {

    Widget mytitle;
    if (grpmsg) {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.people),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    } else {
      mytitle = new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          new Icon(Icons.person),
          new Text('  '),
          new Text(widget.mychat.referralname)
        ],
      );
    }

    return new Scaffold(
      appBar: new AppBar(
        title: mytitle,
        actions: getAppBarActions(context),
      ),
      body: new Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          new Expanded(
            child: new RefreshIndicator(
              child: new ListView.builder(
                itemBuilder: _divBuilder,
                itemCount: listcount,shrinkWrap: true,
              ),
              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,
              )
            ],
          ),
        ],
      ),
    );
  }

  Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    );

  }

  DateTime getDateDiv(int index) {
    DateTime msgdate = DateTime.parse(chatlist[index]['chatdate']).toLocal();
    return msgdate;
  }

  _sendReply() {
    if (_newreplycontroller.text.isEmpty) {
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),
          ],
        ),
      );
    } else {

      DateTime dateSubmit = new DateTime.now();
      var mymessage = _newreplycontroller.text;
      ChatMessage mychat = new ChatMessage(
          widget.mychat.msgkey,
          widget.mychat.referralname,
          replysub,
          oid,
          oname,
          pid,
          pname,
          sender,
          sendname,
          receiver,
          receivename,
          mymessage,
          dateSubmit.toString(),
          widget.mychat.grpid,
          widget.mychat.prid,
          myfcmtoken);
      _doSendReply(mychat);
    }
  }

  _doSendReply(mychat) async {

    var json = jsonCodec.encode(mychat);
    var _url = 'http://$baseurl/csapi/sendchatmsg';

    var http = createHttpClient();
    var response = await http.post(_url, body: json, headers: getJSONHeader());

    var chatresp = await jsonCodec.decode(response.body);
    if (chatresp.contains('GOOD')) {
      _getChats();
      _newreplycontroller.text = '';
      _focusnode.unfocus();

    } else if (chatresp.contains('EMPTY')){
      showDialog(
        context: context,
        child: new AlertDialog(
          content: new Text("Can not submit chat message that is empty"),
          actions: <Widget>[
            new FlatButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.pop(context, false);
                }),

          ],
        ),
      );
    } else {}

  }
}

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();
  var mydate = '';

  _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;
        if (new DateFormat.yMd().format(widget.datediv) == new DateFormat.yMd().format(new DateTime.now())) {
          mydate = 'Today';
        } else {
          mydate = new DateFormat.yMMMEd().format(widget.datediv);
        }
        //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 = [
      new Text(mydate, textAlign: TextAlign.left,),
      new Divider(
        height: 5.0,
        color: Colors.grey,
      ),

      new Flexible(
          child: new Column(
            children: new List.generate(messagecount, (int index) {

              ChatMessage mychat = getChat(index);
              DateTime submitdate = DateTime.parse(mychat.submitdate).toLocal();
              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(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          new Text(
                            mychat.sendname,
                            style: new TextStyle(
                                fontSize: 15.0, fontWeight: FontWeight.bold),
                          ),
                          new Text(' '),
                          new Text(new DateFormat.Hm().format(submitdate)),

                        ],
                      ),

                      new Text('${mychat.message}'),
                    ],
                  ),
                ),
              );
            }
            ),
          ),
      ),

    ];

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

  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'],
    );
  }
}

Body:
You would save yourself so much trouble if you can build your date divider inside your ChatWidget build:

import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Column(

      children: <Widget>[

        new Flexible (child: new ListView.builder(
            shrinkWrap: true,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return new ChatWidget (

              );
            })),
        new Stack(
          alignment: Alignment.centerRight,
          children: <Widget>[
            new TextField(
              decoration: const InputDecoration(
                hintText: 'Chat Reply',
                labelText: 'Chat Reply:',
              ),
              autofocus: false,
              maxLines: 2,
              keyboardType: TextInputType.url,
            ),
            new IconButton(
              icon: new Icon(Icons.send),
              onPressed: null,
              alignment: Alignment.centerRight,
            )
          ],
        ),
      ],
    ));
  }
}

class ChatWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container (child: new Column (children: <Widget>[

      new Divider(height: 15.0, color: Colors.red),
      new Text("My Awesome Date"),
      new Divider(height: 15.0, color: Colors.red),

      new Column(
        children: <Widget>[
          new Card(
              child: new Container(
                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(
                          "Awesome Child",
                          style: new TextStyle(
                              fontSize: 15.0, fontWeight: FontWeight.bold),
                        ),
                        new Text(' @ '),
                        new Text("Awesome Date"),
                      ],
                    ),

                    new Text(
                        'AWESOMMMMMMMMMMMMMMMMMMMMMMMMMMEEEEEEEEEEEEEEEEEEEEEEEEEEE'),
                  ],
                ),
              ))
        ],
      )

    ],),
    );
  }
}

Edit

Try this:

    Widget _divBuilder(BuildContext context, int index) {
    DateTime getdatediv = getDateDiv(index);
    return new Column(children: <Widget>[new MyChatWidget(
      datediv: getdatediv,
      msgkey: msgid,
    ),
    ],);
  }

Update

Generate a list of cards based on the number of message for each divider like this:

return new Column(
      children: new List.generate(
          5, (int index) { //5 = number of cards per date
        return new Card(
          //layout design
        );
      }),
    );

Update
This is a full example of what I meant on List.generate:

import 'package:flutter/material.dart';

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Column(

      children: <Widget>[

        new Flexible (child: new ListView.builder(
            shrinkWrap: true,
            itemCount: 100,
            itemBuilder: (BuildContext context, int index) {
              return new Column(
                children: <Widget>[
                  new Divider(color: Colors.red,),
                  new Text("Date$index"),
                  new ChatWidget(
                    //pass the number of messages for date[index]
                  )
                ],
              );
            })),
        new Stack(
          alignment: Alignment.centerRight,
          children: <Widget>[
            new TextField(
              decoration: const InputDecoration(
                hintText: 'Chat Reply',
                labelText: 'Chat Reply:',
              ),
              autofocus: false,
              maxLines: 2,
              keyboardType: TextInputType.url,
            ),
            new IconButton(
              icon: new Icon(Icons.send),
              onPressed: null,
              alignment: Alignment.centerRight,
            )
          ],
        ),
      ],
    ));
  }
}

class ChatWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Column(
      children: new List.generate(
          5, (int index) { //5 = number of messages of the current dat[index]
        return new Card(
          //layout design
          child: new Text("Message$index"),
        );
      }),
    );
  }
}


来源: stackexchange

问:
How do you configure Gitlab CI dockers to test different requirements (Language env, database, etc.)?
I am creating an API that uses Python, Mongo, and Redis and I wanted to use Gitlab CI.

Do I have to build a Dockerfile with all these requirements? Or is there a way to just write some instructions in the .gitlab-ci.yml and call the different images in Dockerhub?

答:
I found that you can write in a .gitlab-ci.yml a tag:

- services:
   - redis:4.0.2
   - mongo:3.4.10

Which uses other services that are on Dockerhub.

https://docs.gitlab.com/ce/ci/docker/using_docker_images.html#how-to-use-other-images-as-services

ContentLicense: CC BY-SA 3.0


问:
Modify Hashtable value of a specific key
I need to increase the value of a specific key in a Hashtable,
here is my code (I want to create the Hashtable during the function,
and I want the table to be like that - <string><int>):

```<code>public void getMssg(string ipSend, string mssg, Hashtable table)
{
    if (table.Contains(ipSend))
        table[ipSend]++;        //error
}
</code>```

By the way, can I define a Hashtable like I wrote above?

答:
```<code>public void getMssg(string ipSend, string mssg, Hashtable table)
{
    if (table.Contains(ipSend))
    {
        int value = (int)table[ipSend];
        table[ipSend] = value + 1;
    }
}
</code>```

In my opinion, a Dictionary approach would be much better because it is type safe and eliminates the casting. Hashtables are not suitable for this kind of usage. Just an example:

```<code>public void getMssg(string ipSend, string mssg, Dictionary<string,int> table)
{
    if (table.ContainsKey(ipSend))
        table[ipSend] += 1;
    else
        table.Add(ipSend, 1);
}
</code>```

I updated the above code following the advice of @mjwills: TryGetValue outperforms ContainsKey:

```<code>public void getMssg(string ipSend, string mssg, IDictionary<string, int> table)
{
    int result;

    if(!table.TryGetValue(ipSend, out result))
        result = 0;

    table[ipSend] = result + 1;
}
</code>```

Body:
I need to increase the value of a specific key in a Hashtable,
here is my code (I want to create the Hashtable during the function,
and I want the table to be like that - <string><int>):

public void getMssg(string ipSend, string mssg, Hashtable table)
{
    if (table.Contains(ipSend))
        table[ipSend]++;        //error
}

By the way, can I define a Hashtable like I wrote above?

Body:
public void getMssg(string ipSend, string mssg, Hashtable table)
{
    if (table.Contains(ipSend))
    {
        int value = (int)table[ipSend];
        table[ipSend] = value + 1;
    }
}

In my opinion, a Dictionary approach would be much better because it is type safe and eliminates the casting. Hashtables are not suitable for this kind of usage. Just an example:

public void getMssg(string ipSend, string mssg, Dictionary<string,int> table)
{
    if (table.ContainsKey(ipSend))
        table[ipSend] += 1;
    else
        table.Add(ipSend, 1);
}

I updated the above code following the advice of @mjwills: TryGetValue outperforms ContainsKey:

public void getMssg(string ipSend, string mssg, IDictionary<string, int> table)
{
    int result;

    if(!table.TryGetValue(ipSend, out result))
        result = 0;

    table[ipSend] = result + 1;
}


问:
Looking for direction in database/platform choice before beginning a project
I am making a web application and am not sure what is the best tech to use. This will be for a cash strapped charity. Ideally, I'd like the software to be as free to cheap as possible. But, there are corners which shouldn't be cut (security).

The site will accept input from users.

The output must be permission based.

Losing control of the information would be beyond disastrous.

I would like for a user to request a filtered sets of data.

I would like to automate finding duplicates, which are allowed in some columns. However, strings that match may in fact not be actual matches, but must be reviewed.

And I would like to facilitate looking for matches manually (as some matches will not be literal matches and would be difficult to predict).

The users will be non-technical, point and click types. So, that may affect security and usability options.

What is the best platform/database/whatever to secure the data and securely deliver the data (or subsets) to users with appropriate permissions.

答:
The easiest and cheapest platform for this would be Linux, however it's entirely up to you to configure it safely.

Containerize what can be and use a whitelist approach rather than a blacklist approach for your input sanitation.

Use prepared statements in you SQL implementation and hash and salt all user passwords.

Use the latest versions and practices for the language you write the application in.

Your question actually is really broad, I'd recommend you check out OWASP ZAP for securing your web application and perhaps even hire a pentester.


问:
Preserve leading zeros when saving numeric values in database
When executing dynamic MySQL prepared statements to INSERT or UPDATE, leading zeros (such as 0 in 0213123) disappear. How can I prevent this?

```<code>public function update($tablo, array $column, array $form)
{
    global $db;
    $sutun = implode(' = ?, ', array_keys($column)) . ' = ?';
    $where = implode(' = ?, ', array_keys($form)) . ' = ?';
    $stmt = $this->db->prepare("UPDATE $tablo SET $sutun  WHERE $where") or die($this->db->error);
    $form = array_merge($column, $form);
    call_user_func_array(array($stmt,'bind_param'), $this->params($form));
    return $stmt->execute() or die($this->db->error);
}

public function params($params, $types = '', $input = array())
{
    foreach ($params as $key => $val) {
        ${$key} = $val;
        $input[] =& ${$key};

        if (is_numeric($val) AND fmod($val, 1) === 0.00) {
            $types .= 'i';
        } elseif (is_float($val)) {
            $types .= 'd';
        } elseif (is_string($val) OR fmod($val, 1) !== 0.00) {
            $types .= 's';
        } else {
            $types .= 'b';
        }
    }
    array_unshift($input, $types);
    return $input;
}
</code>```

答: This appears to be the behavior of the database. The column is likely a datatype that doesn't allow leading zeros, such as INT. Try changing that column to VARCHAR.

Body:
When executing dynamic MySQL prepared statements to INSERT or UPDATE, leading zeros (such as 0 in 0213123) disappear. How can I prevent this?

public function update($tablo, array $column, array $form)
{
    global $db;
    $sutun = implode(' = ?, ', array_keys($column)) . ' = ?';
    $where = implode(' = ?, ', array_keys($form)) . ' = ?';
    $stmt = $this->db->prepare("UPDATE $tablo SET $sutun  WHERE $where") or die($this->db->error);
    $form = array_merge($column, $form);
    call_user_func_array(array($stmt,'bind_param'), $this->params($form));
    return $stmt->execute() or die($this->db->error);
}

public function params($params, $types = '', $input = array())
{
    foreach ($params as $key => $val) {
        ${$key} = $val;
        $input[] =& ${$key};

        if (is_numeric($val) AND fmod($val, 1) === 0.00) {
            $types .= 'i';
        } elseif (is_float($val)) {
            $types .= 'd';
        } elseif (is_string($val) OR fmod($val, 1) !== 0.00) {
            $types .= 's';
        } else {
            $types .= 'b';
        }
    }
    array_unshift($input, $types);
    return $input;
}


问:
Addition 2 Matrix Erlang
I have a question
I want to do the addition of 2 matrix by row in erlang, I'm trying to apply the code for Haskell:

```<code>add :: Num a => [[a]] -> [[a]] -> [[a]]
add = zipWith $ zipWith (+)
</code>```

I did something like this:

```<code>add([[]],[[]]) -> []
add = zipWith $ zipWith (+)
</code>```

but it get's an error, with the $, I'm really confused. How can I do this in erlang?

And works in this way:

```<code>  add([[ 1, 2 ],[ 3 , 4 ]] , [[ 4 , 5 ],[ 6 , 7 ]] ).
</code>```

Result:

```<code>[[ 6, 8], [ 10, 12]]
</code>```

答:
This is the direction translation of your Haskell function to Erlang:

```<code>add(Xss, Yss) ->
  lists:zipwith(fun(Xs, Ys) -> lists:zipwith(fun(X, Y) -> X + Y end, Xs, Ys) end, Xss, Yss).
</code>```

(+) becomes fun(X, Y) -> X + Y end and since Erlang doesn't have anything like the $ operator or automatic partial application of functions, we need to name all arguments and explicitly pass them to lists:zipwith.

It works as expected:

```<code>1> a:add([[1,2],[3,4]],[[4,5],[6,7]]) == [[5, 7], [9, 11]].
true
</code>```

Title: Addition 2 Matrix Erlang

Body:
I have a question
I want to do the addition of 2 matrix by row in erlang, I'm trying to apply the code for Haskell:

add :: Num a => [[a]] -> [[a]] -> [[a]]
add = zipWith $ zipWith (+)

I did something like this:

add([[]],[[]]) -> []
add = zipWith $ zipWith (+)

but it get's an error, with the $, I'm really confused. How can I do this in erlang?

And works in this way:

  add([[ 1, 2 ],[ 3 , 4 ]] , [[ 4 , 5 ],[ 6 , 7 ]] ).

Result:

[[ 6, 8], [ 10, 12]]

Body:
This is the direction translation of your Haskell function to Erlang:

add(Xss, Yss) ->
  lists:zipwith(fun(Xs, Ys) -> lists:zipwith(fun(X, Y) -> X + Y end, Xs, Ys) end, Xss, Yss).

(+) becomes fun(X, Y) -> X + Y end and since Erlang doesn't have anything like the $ operator or automatic partial application of functions, we need to name all arguments and explicitly pass them to lists:zipwith.

It works as expected:

1> a:add([[1,2],[3,4]],[[4,5],[6,7]]) == [[5, 7], [9, 11]].
true


问:
Show value from returned id on an api request, when this value and id lives on a json
I'm getting info from an API. Between the returned data, i have one id of 'x' value, whitch it's contained on a json file.

This is the code of the api:

```<code>function listData (){
   $http.get('api/Example')
    .then(function(data){
        $scope.list = data.data.Response;
        //console.log($scope.list);
    });
}
</code>```

The mentioned value returned is: IdFruit. This Id have relationship with the values on the next json:

```<code>[
 {
  "Id": 1,
  "value": "Apple"
  },
  {
  "Id": 2,
  "value": "Pear"
  },
  {
  "Id": 3,
  "value": "Mango"
  }
  ]
</code>```

And the code to consume the json is:

```<code>function comboFruit (){
     $http.get('/fruits.json')
     .then(function(data){
        $scope.getFruits = data.data;
        //console.log($scope.getFruits);
     });
    }
</code>```

What i want to do, is to show on my html view the value of the fruit instead of the Id. How can i do that, if i just get the mentioned id of the fruit on the api? I've modify my first code to print on the console the value, and it works:

```<code>function listData (){
       $http.get('api/Example')
        .then(function(data){
            $scope.list = data.data.Response;
            //console.log($scope.list);
                for(var i = 0; i< $scope.list.length; i++){
                    for(var j = 0; j< $scope.getFruits.length; j++){
                        if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
                            $scope.valueType = $scope.getFruits[j].value;
                            //console.log($scope.valueType);
                        }
                    }
                };
        })
    }
</code>```

My problem is to show the $scope.valueType on the html if i'm using ng-repeat:

```<code><tr ng-repeat="info in list">
                <th>{{info.IdFruit}}</th>
</code>```

How can i do that?

Hope you can help me. Thanx in advance.

答:
From what I understood, you are getting the IdFruit from one API call and the value from another. What you can do is create an array of objects to hold the pairs.

```<code>var dict = []; // create an empty array

dict.push({
    key:   "keyName",
    value: "the value"
});
</code>```

So before/in your for loop

```<code>var Controller = function($scope) {
    $scope.pairs = [];
...
}
...
...

for(var i = 0; i< $scope.list.length; i++){
    for(var j = 0; j< $scope.getFruits.length; j++){
        if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
            $scope.valueType = $scope.getFruits[j].value;
            $scope.pairs.push({
                key: $scope.list[i].idFruit, // Can use $scope.getFruits[j].Id since ids are the same
                value: scope.getFruits[j].value
            });
        }
    }
};
</code>```

Now in your ng-repeat:

```<code><tr ng-repeat="fruit in pairs">
    <th>{{fruit.id}}</th> <!-- Only meant to show that you have the pairs now -->
    <th>{{fruit.value}}</th>
</code>```

Body:
I'm getting info from an API. Between the returned data, i have one id of 'x' value, whitch it's contained on a json file.

This is the code of the api:

function listData (){
   $http.get('api/Example')
    .then(function(data){
        $scope.list = data.data.Response;
        //console.log($scope.list);
    });
}

The mentioned value returned is: IdFruit. This Id have relationship with the values on the next json:

[
 {
  "Id": 1,
  "value": "Apple"
  },
  {
  "Id": 2,
  "value": "Pear"
  },
  {
  "Id": 3,
  "value": "Mango"
  }
  ]

And the code to consume the json is:

function comboFruit (){
     $http.get('/fruits.json')
     .then(function(data){
        $scope.getFruits = data.data;
        //console.log($scope.getFruits);
     });
    }

What i want to do, is to show on my html view the value of the fruit instead of the Id. How can i do that, if i just get the mentioned id of the fruit on the api? I've modify my first code to print on the console the value, and it works:

function listData (){
       $http.get('api/Example')
        .then(function(data){
            $scope.list = data.data.Response;
            //console.log($scope.list);
                for(var i = 0; i< $scope.list.length; i++){
                    for(var j = 0; j< $scope.getFruits.length; j++){
                        if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
                            $scope.valueType = $scope.getFruits[j].value;
                            //console.log($scope.valueType);
                        }
                    }
                };
        })
    }

My problem is to show the $scope.valueType on the html if i'm using ng-repeat:

                {{info.IdFruit}}

How can i do that?

Hope you can help me. Thanx in advance.

Body:
From what I understood, you are getting the IdFruit from one API call and the value from another. What you can do is create an array of objects to hold the pairs.

var dict = []; // create an empty array

dict.push({
    key:   "keyName",
    value: "the value"
});

So before/in your for loop

var Controller = function($scope) {
    $scope.pairs = [];
...
}
...
...

for(var i = 0; i< $scope.list.length; i++){
    for(var j = 0; j< $scope.getFruits.length; j++){
        if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
            $scope.valueType = $scope.getFruits[j].value;
            $scope.pairs.push({
                key: $scope.list[i].idFruit, // Can use $scope.getFruits[j].Id since ids are the same
                value: scope.getFruits[j].value
            });
        }
    }
};

Now in your ng-repeat:

<tr ng-repeat="fruit in pairs">
    <th>{{fruit.id}}</th> <!-- Only meant to show that you have the pairs now -->
    <th>{{fruit.value}}</th>


问:
Javascript Interval functions not working
I am currently working on a clicker game for a game dev class I attend, and I can not figure out why my interval functions refuse to work.

What I am trying to achieve with this:

every 100 milliseconds a variable will increase by a number, multiplied by another variable, lets use 10, and i for example.

The code I tried:

```<code>var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  document.getElementById("money").innerHTML = money;
  document.getElementById("i").innerHTML = i;
}
</code>```

This is refusing to work, and I was wondering if it was a problem with defining the variable, or just with the syntax.

Any suggestion?

答:
As per your code:

```<code>var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  document.getElementById("money").innerHTML = money;
  document.getElementById("i").innerHTML = i;
}
</code>```

And your comment:

i and money are defined globally through var tags, and
  document.getelementbyid tags. The console error logged is: Uncaught
  TypeError: Cannot set property 'innerHTML' of null

You need to have two elements with id as money and i respectively to work.

If you will try to execute document.getElementById("money").innerHTML = money; and element with id money does not exist then will throw the error which you are seeing in console.

As a prevention, you can code your function as follows:

```<code>var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  const elM = document.getElementById("money")
  if(elM) elM.innerHTML = money;
  const elI = document.getElementById("i")
  if(elI) elI.innerHTML = i;
}
</code>```

And other possible error that may cause because of money and i variables not define, other fellow community members have explained it.

let interval = setInterval(increment, 100);
let money = 10;
let i = 1;

function increment() {
  money += 10 * i;
  const elM = document.getElementById("money")
  if(elM) elM.innerHTML = money;
  const elI = document.getElementById("i")
  if(elI) elI.innerHTML = i;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div id="money"></div>
<div id="i"></div></code>```

Body:
I am currently working on a clicker game for a game dev class I attend, and I can not figure out why my interval functions refuse to work.

What I am trying to achieve with this:

every 100 milliseconds a variable will increase by a number, multiplied by another variable, lets use 10, and i for example.

The code I tried:

var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  document.getElementById("money").innerHTML = money;
  document.getElementById("i").innerHTML = i;
}

This is refusing to work, and I was wondering if it was a problem with defining the variable, or just with the syntax.

Any suggestion?

Body:
As per your code:

var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  document.getElementById("money").innerHTML = money;
  document.getElementById("i").innerHTML = i;
}

And your comment:

i and money are defined globally through var tags, and
  document.getelementbyid tags. The console error logged is: Uncaught
  TypeError: Cannot set property 'innerHTML' of null

You need to have two elements with id as money and i respectively to work.

If you will try to execute document.getElementById("money").innerHTML = money; and element with id money does not exist then will throw the error which you are seeing in console.

As a prevention, you can code your function as follows:

var interval = setInterval( increment, 100);

function increment(){
  money += 10 * i;
  const elM = document.getElementById("money")
  if(elM) elM.innerHTML = money;
  const elI = document.getElementById("i")
  if(elI) elI.innerHTML = i;
}

And other possible error that may cause because of money and i variables not define, other fellow community members have explained it.

let interval = setInterval(increment, 100);
let money = 10;
let i = 1;

function increment() {
  money += 10 * i;
  const elM = document.getElementById("money")
  if(elM) elM.innerHTML = money;
  const elI = document.getElementById("i")
  if(elI) elI.innerHTML = i;
}

<div id="money"></div>
<div id="i"></div>


问:
Unable to dismiss keyboard with UITextField
I cannot get textFieldShouldEndEditing to call. I have re created the links in interface builder and tried, but nothing seems to work. Any idea why this would not be called?

Edit

I am implementing both -textFieldShouldEndEditing and -textFieldDidFinishEditing. Adding the delegate for the textField didnt help either. The code I am using below is not triggering the log messages.

```<code>-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    NSLog(@"Done editing...");
    [textField resignFirstResponder];
    return YES;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    NSLog(@"Done editing...");
}
</code>```

答:
Have you set the delegate?

If not,set using

```<code>textField.delegate=self;
</code>```

or else,

You must include UITextFieldDelegate in .h file

```<code>@interface yourViewController : UIViewController <UITextFieldDelegate>
</code>```

EDIT:

You have to code in this delegate textFieldDidEndEditing not this textFieldShouldEndEditing

ContentLicense: CC BY-SA 2.5

Body:
I cannot get textFieldShouldEndEditing to call. I have re created the links in interface builder and tried, but nothing seems to work. Any idea why this would not be called?

Edit

I am implementing both -textFieldShouldEndEditing and -textFieldDidFinishEditing. Adding the delegate for the textField didnt help either. The code I am using below is not triggering the log messages.

-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    NSLog(@"Done editing...");
    [textField resignFirstResponder];
    return YES;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    NSLog(@"Done editing...");
}

Body:
Have you set the delegate?

If not,set using

textField.delegate=self;

or else,

You must include UITextFieldDelegate in .h file

@interface yourViewController : UIViewController <UITextFieldDelegate>

EDIT:

You have to code in this delegate textFieldDidEndEditing not this textFieldShouldEndEditing


问:
Show only distinct values in a dropdown
I have a form containing a drop-down.  The form links to a products table. One field in that table is 'mfg name'.  The code below returns the manufacturer for EACH product.  Whereas I seek a drop-down to show a distinct list of manufacturers.  </p>

```<code><div class="form-group">
  <?php echo Form::label('mfg name', 'mfg', array('class' => 'col-md-4 control-label')); ?>
  <div class="col-md-5">
    <!-- Datalist-->
    <input type="text" id="default" list="mfg" placeholder="mfg name" class="form-control input-md" name="mfg">
    <datalist id="mfg">
    <?php
        foreach ($products as $prod){?>
        <option value="<?php echo $prod->mfg; ?>">
    <?php   }?>
    </datalist>
  <datalist id="json-datalist"></datalist>
  </div>
</div>
</code>```

<p>So how can one go about showing distinct manufacturers list as a drop-down?  </p>

答:
A more efficient method would be to query the distinct manufacturers into its own array and iterate over that. However, given the context you have provided and assuming you are using PHP >= 5.5, you can use the array_column function combined with array_unique function:</p>

```<code><?php foreach(array_unique(array_column($products, 'mfg')) as $mfg) {?>
      <option value="<?php echo $mfg; ?>">
<?php   } ?>
</code>```

Title: Show only distinct values in a dropdown

Body:
I have a form containing a drop-down.  The form links to a products table. One field in that table is 'mfg name'.  The code below returns the manufacturer for EACH product.  Whereas I seek a drop-down to show a distinct list of manufacturers.

  <?php echo Form::label('mfg name', 'mfg', array('class' => 'col-md-4 control-label')); ?>

    <input type="text" id="default" list="mfg" placeholder="mfg name" class="form-control input-md" name="mfg">
    <datalist id="mfg">
    <?php
        foreach ($products as $prod){?>
        <option value="<?php echo $prod->mfg; ?>">
    <?php   }?>
    </datalist>
  <datalist id="json-datalist"></datalist>

So how can one go about showing distinct manufacturers list as a drop-down?

Body:
A more efficient method would be to query the distinct manufacturers into its own array and iterate over that. However, given the context you have provided and assuming you are using PHP >= 5.5, you can use the array_column function combined with array_unique function:

<?php foreach(array_unique(array_column($products, 'mfg')) as $mfg) {?>
      <option value="<?php echo $mfg; ?>">
<?php   } ?>


问:
What is the difference between router.METHOD() and router.route() methods in Express
I've seen code written both ways.

```<code>router.get(path, callback)
</code>```

and

```<code>router.route(path).get(callback)
</code>```

From the surrounding code they look equivalent.  The docs are here:

router.route

and

router.METHOD

where method can be get, post, etc.

Why are there two ways to do this?  I've read the docs and they did not help so much.

答:
I always use router.METHOD(path, callback)

So ONE method, ONE path, handled with ONE callback.

The second method you named can have ONE path that handles multiples methods.

So you can have both a get and a post method on path /user.

If you want to setup, for example, something like CRUD routes like this:

Then I would recommend you use router.METHOD(path, callback) approach, as you want to have unique paths for each route.

Body:
I've seen code written both ways.

router.get(path, callback)

and

router.route(path).get(callback)

From the surrounding code they look equivalent.  The docs are here:

router.route

and

router.METHOD

where method can be get, post, etc.

Why are there two ways to do this?  I've read the docs and they did not help so much.


问:
How to vertically center a span/svg inside a div
Fiddle: https://jsfiddle.net/6yfv3u5m/

HTML:

```<code><div id="dvMore">
    <div id="dvMore2">
        <span id="spMore">View More</span>
        <svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#000000" d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"></path></svg>
    </div>
</div>
</code>```

I don't have a height, just dynamic content.

Edit: Tried to set dvMore2 to vertically-align: center. Also tried to add a placeholder span and set the vertical-align to center but none of them worked.

答:
Add display: flex; align-items: center;

https://jsfiddle.net/6yfv3u5m/1/

Body:
Fiddle: https://jsfiddle.net/6yfv3u5m/

HTML:

        View More
        <svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#000000" d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"></path></svg>

I don't have a height, just dynamic content.

Edit: Tried to set dvMore2 to vertically-align: center. Also tried to add a placeholder span and set the vertical-align to center but none of them worked.


问:
regex for email validation Not Working with Subdomains?
I'm using the following for email validation:

```<code>var filter = /^([\w]+)(.[\w]+)*@([\w]+)(.[\w]{2,3}){1,2}$/; // For Email Validation

if (filter.test(emailInputVal))) {console.log('good')}
</code>```

For some reason the above does not work with emails that have a subdomain Any ideas why?

```<code>xxxx@xxx.xxx.com
</code>```

Thanks

答:
That is one weird regex. It's certainly not doing what you're expecting it to do, for example because the dot isn't escaped when you do mean a literal dot.

Since it's impossible to really validate an email address with a regex anyway - why not go for something simpler?

```<code>/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i
</code>```

This will still match some invalid addresses and will reject some valid addresses (as all readable regexes do), but in the end you have to send a confirmation mail to a user-submitted mail address and see if you get a reply if you truly want to validate it.

Body:
I'm using the following for email validation:

var filter = /^([\w]+)(.[\w]+)*@([\w]+)(.[\w]{2,3}){1,2}$/; // For Email Validation

if (filter.test(emailInputVal))) {console.log('good')}

For some reason the above does not work with emails that have a subdomain Any ideas why?

xxxx@xxx.xxx.com

Thanks

Body:
That is one weird regex. It's certainly not doing what you're expecting it to do, for example because the dot isn't escaped when you do mean a literal dot.

Since it's impossible to really validate an email address with a regex anyway - why not go for something simpler?

/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i

This will still match some invalid addresses and will reject some valid addresses (as all readable regexes do), but in the end you have to send a confirmation mail to a user-submitted mail address and see if you get a reply if you truly want to validate it.


答:
This should work

```<code> function listData (){
           $http.get('api/Example')
            .then(function(data){
                $scope.list = data.data.Response;
                //console.log($scope.list);
                    for(var i = 0; i< $scope.list.length; i++){
                        for(var j = 0; j< $scope.getFruits.length; j++){
                            if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
                                $scope.list[i].value = $scope.getFruits[j].value;
                            }
                        }
                    };
            })
        }
</code>```

html

```<code><tr ng-repeat="info in list">
                <th>{{info.value}}</th>
</code>```

Title: Show value from returned id on an api request, when this value and id lives on a json

Body:
This should work

 function listData (){
           $http.get('api/Example')
            .then(function(data){
                $scope.list = data.data.Response;
                //console.log($scope.list);
                    for(var i = 0; i< $scope.list.length; i++){
                        for(var j = 0; j< $scope.getFruits.length; j++){
                            if($scope.list[i].IdFruit === $scope.getFruits[j].Id){
                                $scope.list[i].value = $scope.getFruits[j].value;
                            }
                        }
                    };
            })
        }

html

<tr ng-repeat="info in list">
                <th>{{info.value}}</th>


问:
Is it possible to create typings, where function return value is selected by the string literal of function parameter
I've been trying to figure out how to implement typings for plugin based system, where base code actually doesn't know all the typings that system supports after some plugins has been loaded in.

I have tried to implement this by allowing plugins to declare ambient typings and extend that way original interfaces.

I hoped that with some string matching magic I could make it work a bit similar way with this:

```<code>type t1 = {
  type: 'foo';
  test: number;
};

type t2 = {
  type: 'bar';
  test: string;
};

type t = t1 | t2;

const tx1: t = {
  type: 'foo',
  test: 1
};

const tx2: t = {
  type: 'foo',
  test: 'this fails, because if type = foo, then test must be a number'
};

const txbar: t = {
  type: 'bar',
  test: 'this works because with bar object test can be string'
};
</code>```

So for the plugin system I would like to implement same kind of string matching possibility, but with using interfaces:

```<code>interface PluginClass1 {}
interface PluginClass2 {}

interface PluginApi {
  getPlugin: (pluginName: 'plug1') => PluginClass1
}

interface PluginApi {
  getPlugin: (pluginName: 'plug2') => PluginClass2
}

class PluginManager implements PluginApi {
  plugins = {};
  getPlugin(pluginName) {
    return <any> this.plugins[pluginName];
  }
}

const manager = new PluginManager();

// here I would like to get correctly typed return value
// according to name string (this doesn't work though)
const plugin1 = manager.getPlugin('plug1');
const plugin2 = manager.getPlugin('plug2');
</code>```

Is there any way to make this kind of typing scheme to work or is there some better way for typing extendable interfaces?

答:
The super easy solution: Manually declare that manager is a plugin api:

const manager: PluginApi = new PluginManager()

Then plugin1 and plugin2 will correctly be inferred to be PluginClass1 and PluginClass2 respectively.

EDIT: In the above solution, you may also want to declare each getPlugin signature as a method, not a function assigned to a property. Eg: getPlugin(pluginName: 'plug1'): PluginClass1 instead of getPlugin: (pluginName: 'plug1') => PluginClass1. That way you can take advantage of function overloading.

However, if you don't want to declare every usage of PluginManager as a PluginApi, you'll have to make sure that the actual getPlugin implementation has the correct types (since typescript won't do this for you, although I'm not sure why not). So you need to give it the correct type signature manually. One way to do this is with a mapped type. But do do this, each plugin needs to declare its name and return type (instead of declaring the method signature itself).

```<code>interface PluginClass1 {}
interface PluginClass2 {}

// Note that each plugin now extends a different interface.  One that declares
// the name and return type, rather than the method signature.
interface PluginApiTypes {
  'plug1': PluginClass1
}

interface PluginApiTypes {
  'plug2': PluginClass2
}

// Then we combine all those names and return types into a method:
interface PluginApi {
    getPlugin<K extends keyof PluginApiTypes>(pluginName: K): PluginApiTypes[K];
}

class PluginManager implements PluginApi {
  plugins = {};
  // Unfortunatly we have to replicate the signature of getPlugin here,  since typescript will not infer it.
  getPlugin<K extends keyof PluginApiTypes>(pluginName: K): PluginApiTypes[K] {
    return <any> this.plugins[pluginName];
  }
}

const manager = new PluginManager();

// Now should be correctly inferred.
const plugin1 = manager.getPlugin('plug1');
const plugin2 = manager.getPlugin('plug2');
</code>```

It's perhaps not an ideal solution, but it does work. Maybe someone more knowledgable than I can shed some light on why the type signature of getPlugin isn't inferred from the interface.

Body:
I've been trying to figure out how to implement typings for plugin based system, where base code actually doesn't know all the typings that system supports after some plugins has been loaded in.

I have tried to implement this by allowing plugins to declare ambient typings and extend that way original interfaces.

I hoped that with some string matching magic I could make it work a bit similar way with this:

type t1 = {
  type: 'foo';
  test: number;
};

type t2 = {
  type: 'bar';
  test: string;
};

type t = t1 | t2;

const tx1: t = {
  type: 'foo',
  test: 1
};

const tx2: t = {
  type: 'foo',
  test: 'this fails, because if type = foo, then test must be a number'
};

const txbar: t = {
  type: 'bar',
  test: 'this works because with bar object test can be string'
};

So for the plugin system I would like to implement same kind of string matching possibility, but with using interfaces:

interface PluginClass1 {}
interface PluginClass2 {}

interface PluginApi {
  getPlugin: (pluginName: 'plug1') => PluginClass1
}

interface PluginApi {
  getPlugin: (pluginName: 'plug2') => PluginClass2
}

class PluginManager implements PluginApi {
  plugins = {};
  getPlugin(pluginName) {
    return <any> this.plugins[pluginName];
  }
}

const manager = new PluginManager();

// here I would like to get correctly typed return value
// according to name string (this doesn't work though)
const plugin1 = manager.getPlugin('plug1');
const plugin2 = manager.getPlugin('plug2');

Is there any way to make this kind of typing scheme to work or is there some better way for typing extendable interfaces?

Body:
The super easy solution: Manually declare that manager is a plugin api:

const manager: PluginApi = new PluginManager()

Then plugin1 and plugin2 will correctly be inferred to be PluginClass1 and PluginClass2 respectively.

EDIT: In the above solution, you may also want to declare each getPlugin signature as a method, not a function assigned to a property. Eg: getPlugin(pluginName: 'plug1'): PluginClass1 instead of getPlugin: (pluginName: 'plug1') => PluginClass1. That way you can take advantage of function overloading.

However, if you don't want to declare every usage of PluginManager as a PluginApi, you'll have to make sure that the actual getPlugin implementation has the correct types (since typescript won't do this for you, although I'm not sure why not). So you need to give it the correct type signature manually. One way to do this is with a mapped type. But do do this, each plugin needs to declare its name and return type (instead of declaring the method signature itself).

interface PluginClass1 {}
interface PluginClass2 {}

// Note that each plugin now extends a different interface.  One that declares
// the name and return type, rather than the method signature.
interface PluginApiTypes {
  'plug1': PluginClass1
}

interface PluginApiTypes {
  'plug2': PluginClass2
}

// Then we combine all those names and return types into a method:
interface PluginApi {
    getPlugin<K extends keyof PluginApiTypes>(pluginName: K): PluginApiTypes[K];
}

class PluginManager implements PluginApi {
  plugins = {};
  // Unfortunatly we have to replicate the signature of getPlugin here,  since typescript will not infer it.
  getPlugin<K extends keyof PluginApiTypes>(pluginName: K): PluginApiTypes[K] {
    return <any> this.plugins[pluginName];
  }
}

const manager = new PluginManager();

// Now should be correctly inferred.
const plugin1 = manager.getPlugin('plug1');
const plugin2 = manager.getPlugin('plug2');

It's perhaps not an ideal solution, but it does work. Maybe someone more knowledgable than I can shed some light on why the type signature of getPlugin isn't inferred from the interface.


问:
OneNote FSSHTTP
For one of our application that needs to get connected to Office365 and Sharepoint Online we are implementing FSSHTTP functions. This to be able to modify Word documents. The impact is that once you start supporting FSSHttp, then all the other applications do use FSSHTTP as well.

We managed to be able to read and modify word files. We now need to manage OneNote files as well.

Unfortunately the format of a OneNote file in FSSHTTP is very different from the one of Word.

Word comes into zipped XML files, while the OneNote content just comes into an array of bytes.

We have arrays like this
(length=97):02 00 00 80 0F 00 00 00 1C 00 00 00 0A 00 DD 34 00 88 77 34 00 0C FE 1C 00 10 3E 1C 00 14 84 1C 00 14 7A 1D 00 14 22 1C 00 1C 5B 1E 00 1C 2C 34 00 20 13 1E 00 24 00 0C 04 01 00 00 00 01 00 00 00 49 2E 2B 47 0C 00 00 00 53 00 61 00 6C 00 75 00 74 00 00 00 04 00 00 00 31 00 00 00 01 00 00 00

(length=87):02 00 00 80 0F 00 00 00 1C 00 00 00 0A 00 DD 34 00 88 77 34 00 0C FE 1C 00 10 3E 1C 00 14 84 1C 00 14 7A 1D 00 14 22 1C 00 1C 5B 1E 00 1C 2C 34 00 20 13 1E 00 24 00 0C 04 01 00 00 00 01 00 00 00 49 2E 2B 47 02 00 00 00 00 00 04 00 00 00 31 00 00 00 01 00 00 00

We understand the content is in Unicode 16. We managed to find some content, but we can't really figure out what this content is and how it is formatted.

Has anybody already used this? Do you know if the OneNote content is FSSHTTP is into XML fragment (as it is for OpenXML documents)?

We could not find any documentation explaining or describing the format.

It would be very much appreciated if somebody could share some pointers, or links.

Many thanks in advance

Gilles

答:
https://msdn.microsoft.com/en-us/library/dd924743(v=office.12).aspx

The .one file format is documented in the link above. The OneNote REST API (or Graph API) can give you an HTML representation of OneNote content, but I don't think this is what you're looking for.

Title: OneNote FSSHTTP