Flutter构建聊天页面+接入图灵机器人

  • Post author:
  • Post category:其他


作为一个专注flutter开发十年的老人,我想说talk is cheap, show me the gif:

在这里插入图片描述


这里特别感谢一下screenToGif软件,只有3MB大小,却是录屏转gif的神器,墙裂推荐给大家!



如何用flutter构建一个聊天页面?

1.引入bubble: ^1.1.9这个插件,这是一个可以带口子的聊天框,各种样式设定都有,一下对它封装制造一个自定义组件ChatRow,源码如下:

class ChatRow extends StatelessWidget{
  String avatarLocalSavedPath;
  String content;
  bool isMyself;

  ChatRow({@required this.avatarLocalSavedPath, 
		  @required this.content, 
		  @required this.isMyself});

  @override
  Widget build(BuildContext context) {
    if(isMyself) {
      return Row(
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Bubble(
            margin: BubbleEdges.only(top: 10),
            alignment: Alignment.topRight,
            nip: BubbleNip.rightTop,
            child: Container(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width/2
                ),
                child: Text(content)
            ),
          ),
          SizedBox(
              height: 50,
              child: Image.asset(this.avatarLocalSavedPath)),
        ],
      );
    }else{
      return Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          SizedBox(
              height: 50,
              child: Image.asset("assets/TuringRobot.jpg")
          ),
          Bubble(
            margin: BubbleEdges.only(top: 10),
            alignment: Alignment.topLeft,
            nip: BubbleNip.leftTop,
            child: Container(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width/2
                ),
                child: Text(this.content)
            ),
          ),
        ],
      );
    }
  }
}

这里三个参数分别代表用户头像储存路径、说话的内容和是不是用户自己(主要用于区分左右行构建),大家伙可以根据自己的需求改良。比如添加用户ID变量,尺寸引入screenUtil作全款型适配。

2.底层输入框自定义组件

这里完全模仿了微信,觉得微信的前端码农还是挺厉害的,输入文字切发送按钮,文字消除切表情按钮,很好很方便。这里巧用TextField的onChanged回调方法和发送按钮的onPressed方法解决切换问题。

3.底层输入框和聊天行的配合

第一个就是输入框弹起时和聊天行一起上拉

这里在Column控件外层套用一个SingleChildScrollView

  @override
  Widget build(BuildContext context) {
    lcr=_getList(Provider.of<ChatContentProvider>(context).lcim);
    // TODO: implement build
    return SingleChildScrollView(
      child: Column(
            children: <Widget>[
              Container(
                height: MediaQuery.of(context).size.height*8/10,
                  child: GestureDetector(
                    onTap: (){
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
                    child: ListView(
                      //padding: EdgeInsets.only(top: max(MediaQuery.of(context).size.height/2-lcr.length*30, 0)),
                      reverse: true,
                      children: lcr,
                    ),
                  )
              ),
              BottomInput(),
            ],
      ),
    );
  }

第二个是保持输入框和ListView里最后一条信息贴合

列表添加收到信息的顺序要注意

  void addChatItem(ChatItemModel cim){
    if(lcim.isEmpty)lcim.add(cim);
    else
    lcim.insert(0, cim);
    notifyListeners();
  }

再就是ListView的reverse属性设置为true

ListView(
         reverse: true,
         children: lcr,
        ),

第三个就是聊天框最大宽度的限制

Container(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width/2
                ),
                child: Text(content)
            ),
          ),

页面的数据传入是在widget树上层绑定这个ChatContentProvider,这个信息主要就是维护一个聊天行的List。



如何用flutter接入图灵机器人?

注册->拿到API_KEY和USER_ID->用dio库直接发送请求就好了

这里记住李文周老师的一句话:一个请求对应一个响应

import 'package:dio/dio.dart';
import 'dart:convert' as Convert;

class SelfHttpUtil{
  static const API_KEY="填你自己的秘钥";
  static const USER_ID="填你自己的用户号";
  Dio dio=new Dio();

  Future<String> getHttp(String sentMsg) async{
    try{
      Response response = await dio.post(
        "http://openapi.tuling123.com/openapi/api/v2",
        data: {
          "reqType":0,
          "perception": {
            "inputText": {
              "text": sentMsg
            },
          },
          "userInfo": {
            "apiKey": API_KEY,
            "userId": USER_ID,
          }
        }
      );
      print("get response from turing robot server");
      print(response);
      Map<String, dynamic> data=Convert.jsonDecode(response.data);
      print("data is $data");
      List list=data["results"];
      print("list is $list");
      String replyContent=list[0]["values"]["text"];
      print(replyContent);
      return replyContent;
    }catch(e){
      print(e);
    }
  }
}

最后我想说,我只从事了flutter开发2周,有兴趣的话联系我吧,一起做点有意义的事。



版权声明:本文为JACK_GEN123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。