欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-04 09:54:04
...

作为一个专注flutter开发十年的老人,我想说talk is cheap, show me the gif:
Flutter构建聊天页面+接入图灵机器人
这里特别感谢一下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周,有兴趣的话联系我吧,一起做点有意义的事。

相关标签: flutter开发