2017-12-21 4 views
1

여러 가지 해결책을 찾아 보았지만 어느 것도 내 구성에 맞지 않아 도움이 필요하지 않습니다. 여기에 모든 코드를 넣고 어디서 ScrollController를 적용 할 지 아는 사람이 있는지 확인합니다. 원래 ListView를 시도했지만 futureResponse의 ListView 빌더 아래에 다른 항목을 동적으로 빌드합니다. 동적 ListView 아래쪽으로 스크롤하십시오.

import 'dart:async'; 
import 'dart:io'; 
import 'dart:typed_data'; 


import 'dart:convert'; 
import 'package:http/http.dart' as http; 
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; 
import 'package:image_picker/image_picker.dart'; 
import 'package:cswauthapp/ShowPic.dart'; 
import 'package:path/path.dart' as path; 
import 'package:video_player/video_player.dart'; 
import 'package:cswauthapp/vplayer.dart' as vplayer; 

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'; 
    Future<http.Response> _responseFuture; 
    var _urlDates = ''; 
    Future<File> _imageFile; 
    String myimage; 
    String myvideo; 
    File myimagefile; 
    File myvidfile; 
    Future<int> myimagelength; 
    String myext; 
    VideoPlayerController vcontroller; 
    bool isImage = false; 
    bool isVideo = false; 
    //ScrollController scontroller = new ScrollController(); 

    _getPrefs() async { 
    prefs = await SharedPreferences.getInstance(); 

    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 if (authlevel == 1) { 
      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(); 
    _urlDates = 
     'http://loop-dev.clinicalsoftworks.com/chat/messages/getdates/${widget 
     .mychat.msgkey}'; 
    _responseFuture = http.get(_urlDates, headers: getAuthHeader()); 
    } 

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


    _getChats() async { 

    var _url = 
     'http://loop-dev.clinicalsoftworks.com/chat/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),() { 
     setState(() { 
     _responseFuture = http.get(_urlDates, headers: getAuthHeader()); 
     print('RUNNING LOAD AFTER REFRESH AGAIN'); 
     }); 
     completer.complete(); 
    }); 
    return completer.future; 
    } 

    Future<String> doImageString() async { 

    return (await _imageFile).path.substring((await _imageFile).path.length - 3); 
    } 

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

    var _children = <Widget>[ 
     new Flexible(
     child: new RefreshIndicator(
      child: new FutureBuilder(
       future: _responseFuture, 
       builder: (BuildContext context, 
        AsyncSnapshot<http.Response> response) { 
       if (!response.hasData) { 
        return const Center(
        //child: const Text('Loading Dates...'), 
        child: const CircularProgressIndicator(), 
       ); 
       } else if (response.data.statusCode != 200) { 
        return const Center(
        child: const Text('Error loading data'), 
       ); 
       } else { 
        List<dynamic> json = JSON.decode(response.data.body); 
        return new MyChatList(json); 
       } 
       }, 
      ), 
      onRefresh: _onRefresh), 
    ), 
     new Container(
      alignment: Alignment.bottomLeft, 
      padding: new EdgeInsets.only(left: 10.0), 
      child: new FutureBuilder<File>(
       future: _imageFile, 
       builder: (BuildContext context, AsyncSnapshot<File> snapshot) { 
       if (snapshot.connectionState == ConnectionState.done) { 
        //return new Image.file(snapshot.data); 
        myimagefile = snapshot.data; 
        myext = path.extension(myimagefile.path); 
        if (myext == '.jpg') { 
        isImage = true; 
        return new Column(
         mainAxisAlignment: MainAxisAlignment.start, 
         children: <Widget>[ 
         new Container(
          alignment: Alignment.bottomLeft, 
          width: 150.0, 
          child: new Image.file(snapshot.data), 
         ), 
         new FlatButton(
          onPressed: _doClear, child: new Text('Clear Image')) 
         ], 
        ); 
        } else { 
        isVideo = true; 
        myvidfile = new File(snapshot.data.path.replaceAll('file://', '')); 
        vcontroller = new VideoPlayerController(myimagefile.path)..initialize(); 
        return new Column(
         mainAxisAlignment: MainAxisAlignment.start, 
         children: <Widget>[ 
         new Container(
          alignment: Alignment.bottomLeft, 
          width: 300.0, 
          child: new vplayer.VideoCard(controller: vcontroller, title: widget.mychat.referralname,subtitle: 'Video',), 
         ), 
         new FlatButton(
          onPressed: _doClear, child: new Text('Clear Video')) 
         ], 
        ); 
        } 

       } else { 
        return const Text(''); 
       } 
       }) 
    ), 
     new Divider(
     height: 5.0, 
     color: Colors.grey, 
    ), 
     new Row(
     crossAxisAlignment: CrossAxisAlignment.end, 
     children: <Widget>[ 
      new Container(
      alignment: Alignment.bottomLeft, 
      //width: 50.0, 
      child: new IconButton(
       icon: new Icon(Icons.add_a_photo), 
       onPressed: _pickImage, 
       alignment: Alignment.bottomLeft, 
      ), 
     ), 
      new Flexible(
      child: new Container(
       alignment: Alignment.center, 
       //width: 350.0, 
       child: new TextField(
       decoration: const InputDecoration(
        hintText: 'Reply', 
        labelText: 'Reply:', 
       ), 
       autofocus: false, 
       focusNode: _focusnode, 
       maxLines: 1, 
       controller: _newreplycontroller, 
       keyboardType: TextInputType.text, 
      ), 
      ), 
     ), 
      new Container(
       alignment: Alignment.bottomRight, 
       //width: 50.0, 
       child: new IconButton(
       icon: new Icon(Icons.send), 
       onPressed: _sendReply, 
       alignment: Alignment.centerRight, 
       disabledColor: Colors.grey, 
      )), 
     ], 
    ), 
    ]; 

    return new Scaffold(
     appBar: new AppBar(
     title: mytitle, 
     actions: getAppBarActions(context), 
    ), 
     body: new Column(
     children: _children, 
    ), 
    ); 
    } 

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

    _doClear() { 
    setState(() { 
     _imageFile = null; 
    }); 
    } 

    _pickImage() async { 
    await setState(() { 
     _imageFile = ImagePicker.pickImage(maxWidth: 600.0); 
    }); 
    } 

    _sendReply() { 
    if (_newreplycontroller.text.isEmpty && myimagefile == null) { 
     showDialog(
     context: context, 
     child: new AlertDialog(
      content: new Text("There is no message to submit"), 
      actions: <Widget>[ 
      new FlatButton(
       child: const Text('OK'), 
       onPressed:() { 
        Navigator.pop(context, false); 
       }), 
      ], 
     ), 
    ); 
    } else { 
     TextInputAction.done; 
     DateTime dateSubmit = new DateTime.now(); 
     if (myimagefile != null) { 
     if (isImage) { 
      List<int> imageBytes = myimagefile.readAsBytesSync(); 
      myimage = BASE64.encode(imageBytes); 
     } 
     if (isVideo) { 
      List<int> imageBytes = myvidfile.readAsBytesSync(); 
      myvideo = BASE64.encode(imageBytes); 
     } 

     } else { 
     myimage = ''; 
     myvideo = ''; 
     } 
     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, 
      myimage, 
      myvideo, 
      myext 
    ); 
     _doSendReply(mychat); 
    } 
    } 

    _doSendReply(mychat) async { 
    var json = jsonCodec.encode(mychat); 
    var _url = 'http://loop-dev.clinicalsoftworks.com/chat/messages/send'; 

    //var request = new http.MultipartRequest('POST', _url) 
    var http = createHttpClient(); 
    var response = await http.post(_url, body: json, headers: getJSONHeader()); 

    var chatresp = await jsonCodec.decode(response.body); 
    if (chatresp.contains('GOOD')) { 
     setState(() { 
     _responseFuture = http.get(_urlDates, headers: getAuthHeader()); 
     _doClear(); 
     print('RUNNING LOAD AFTER SEND AGAIN'); 
     }); 
     _newreplycontroller.text = ''; 
     _focusnode.unfocus(); 
    } else if (chatresp.contains('EMPTY')) { 
     showDialog(
     context: context, 
     child: new AlertDialog(
      content: new Text("There is no message to submit"), 
      actions: <Widget>[ 
      new FlatButton(
       child: const Text('OK'), 
       onPressed:() { 
        Navigator.pop(context, false); 
       }), 
      ], 
     ), 
    ); 
    } else {} 
    } 
} 

class MyChatList extends StatelessWidget { 
    final List<dynamic> elementList; 
    static ScrollController _scrollController; 

    MyChatList(this.elementList); 

    List<Widget> _getChildren() { 
    List<Widget> children = []; 
    elementList.forEach((element) { 
     children.add(
     new MyChatWidget(
      datediv: element['msgdate'], msgkey: element['msgkey']), 
    ); 
     //_scrollController.animateTo(0.0, duration: const Duration(milliseconds: 300), curve: Curves.easeOut); 
    }); 
    return children; 
    } 

    @override 
    Widget build(BuildContext context) { 
    //_scrollController.position.maxScrollExtent; 
    return new ListView(
     shrinkWrap: true, 
     controller: _scrollController, 
     reverse: false, 
     children: _getChildren(), 
    ); 

    } 
} 

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

    final String datediv; 
    final String msgkey; 

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

class _MyChatWidgetState extends State<MyChatWidget> { 
    List<Widget> messagelist; 
    int messagecount = 0; 
    var jsonCodec = const JsonCodec(); 
    var mydate = ''; 
    var _urlMessages = ''; 
    PageStorageKey _key; 
    Future<http.Response> _responseFuture; 
    List messList; 
    var mybytes; 
    File myimageview; 
    Image newimageview; 
    String imgStr; 
    String vidStr; 

    @override 
    void initState() { 
    super.initState(); 
    if (new DateFormat.yMd().format(DateTime.parse(widget.datediv)) == 
     new DateFormat.yMd().format(new DateTime.now())) { 
     mydate = 'Today'; 
    } else { 
     mydate = new DateFormat.yMMMEd().format(DateTime.parse(widget.datediv)); 
    } 
    DateChatMessage dcm = 
     new DateChatMessage(widget.msgkey, widget.datediv.toString()); 
    var json = jsonCodec.encode(dcm); 
    _urlMessages = 
     'http://loop-dev.clinicalsoftworks.com/chat/messages/getbydate'; 
    _responseFuture = 
     http.post(_urlMessages, body: json, headers: getAuthHeader()); 

    //controller = new TabController(length: 4, vsync: this); 
    //_getMessages(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    _key = new PageStorageKey('${widget.datediv.toString()}'); 
    VideoPlayerController vcontroller; 
    return new Column(
     children: <Widget>[ 
     new Container(
      child: new Text(
      mydate, 
      textAlign: TextAlign.left, 
      style: new TextStyle(
       color: Colors.grey, 
       fontWeight: FontWeight.bold, 
      ), 
     ), 
      alignment: Alignment.centerLeft, 
      padding: new EdgeInsets.only(left: 10.0), 
     ), 
     new Container(
      child: new Divider(
      height: 5.0, 
      color: Colors.grey, 
     ), 
      padding: new EdgeInsets.only(left: 10.0, right: 10.0), 
     ), 
     /**/ 
     new FutureBuilder(
      future: _responseFuture, 
      builder: 
       (BuildContext context, AsyncSnapshot<http.Response> response) { 
      if (!response.hasData) { 
       return const Center(
       child: const Text('Loading Messages...'), 
      ); 
      } else if (response.data.statusCode != 200) { 
       return const Center(
       child: const Text('Error loading data'), 
      ); 
      } else { 
       List<dynamic> json = JSON.decode(response.data.body); 
       messagelist = []; 
       json.forEach((element) { 
       DateTime submitdate = 
        DateTime.parse(element['submitdate']).toLocal(); 
       String myvideo = element['chatvideo']; 
       String myimage = element['chatimage']; 
       if (myimage != null) { 
        imgStr = 'http://loop-dev.clinicalsoftworks.com/chat/getimage/'+element['chatimage']; 

       } else if (myvideo != null) { 
        vidStr = 'http://loop-dev.clinicalsoftworks.com/chatuploads/'+element['chatvideo']; 
        vcontroller = new VideoPlayerController(vidStr)..initialize(); 
       } 
       _showLgPic() { 
        Route route = new MaterialPageRoute(
        settings: new RouteSettings(name: "/ShowPic"), 
        builder: (BuildContext context) => new ShowPic(
          image: imgStr, 
         ), 
       ); 
        Navigator.of(context).push(route); 
       } 

       _addImage() { 
        //assert(imgStr != null); 
        //myimageview = new Image.memory(mbytes); 
        new GestureDetector(
        /*child: new Image(
         image: newimageview.image, 
         width: 300.0, 
        ),*/ 
        child: new Image.network(imgStr), 
        onTap: _showLgPic, 
       ); 
       } 

       _addNoImage() { 
        assert(imgStr == null); 
        new Text(''); 
       } 

       _showAssets() { 
        if (imgStr != null) { 
        new GestureDetector(
         child: new Image.network(
         imgStr, 
         width: 300.0, 
        ), 
         onTap: _showLgPic, 
        ); 
        } else if (vidStr != null) { 
        new vplayer.VideoCard(controller: vcontroller,title: element['referralname'],subtitle: 'video',); 
        } else { 
        new Container(); 
        } 
       } 

       messagelist.add(
        new Container(
        //width: 300.0, 
        padding: new EdgeInsets.all(10.0), 
        child: new Column(
         mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
         crossAxisAlignment: CrossAxisAlignment.stretch, 
         mainAxisSize: MainAxisSize.min, 
         children: <Widget>[ 
         new Container(
          padding: new EdgeInsets.only(bottom: 5.0), 
          child: new Row(
          mainAxisSize: MainAxisSize.min, 
          children: <Widget>[ 
           new CircleAvatar(
           child: new Text(
            element['sendname'][0], 
            style: new TextStyle(fontSize: 15.0), 
           ), 
           radius: 12.0, 
          ), 
           new Text(' '), 
           new Text(
           element['sendname'], 
           style: new TextStyle(
            fontSize: 15.0, 
            fontWeight: FontWeight.bold), 
          ), 
           new Text(' '), 
           new Text(
           new DateFormat.Hm().format(submitdate), 
           style: new TextStyle(
            color: Colors.grey, fontSize: 12.0), 
          ), 
           //new Text(submitdate.toLocal().toString()) 
          ], 
         ), 
         ), 

         new Row(
          children: <Widget>[ 
          new Text('   '), 
          new Flexible(
           child: new Text('${element['message']}'), 
          ) 
          ], 
         ), 
         new Container(
          width: 300.0, 
          child: new Row(
           children: <Widget>[ 
           new Text('   '), 
           //_showAssets(), 
           imgStr != null 
            ? new GestureDetector(
             child: new Image.network(
              imgStr, 
              width: 300.0, 
             ), 
             onTap: _showLgPic, 
            ) 
            : vidStr != null 
            ? new Flexible(child: new vplayer.VideoCard(controller: vcontroller,title: element['referralname'],subtitle: 'video',),) 
            : new Container(), 
           ], 
          ) 
         ), 
         ], 
        ), 
       ), 
       ); 
       }); 
       return new Column(children: messagelist); 
      } 
      }, 
     ), 
     ], 
    ); 
    } 
} 

어떤 도움

크게 이해할 수있을 것이다.

답변

1

가장 쉬운 방법은 reverse 속성을 ListView으로 설정하고 컨트롤러를 사용하여 0.0으로 스크롤하십시오. 다음

ListView(
    shrinkWrap: true, 
    controller: _scrollController, 
    reverse: true, \\ <- set this true 
    children: _getChildren(), 
); 

_scrollController.animateTo(
     0.0, 
     curve: Curves.easeOut, 
     duration: const Duration(milliseconds: 300), 
    );