flutter Chat Messaging UI 实现一个男神使用的聊天气泡界面

2,072 阅读6分钟

flutter Chat Messaging UI 实现一个男神使用的聊天气泡界面

 我们日常上网交流都会用到聊天工具,与男神聊天的UI界面肯定要特别好看,常见的聊天工具的聊天界面都是气泡样子的,聊天界面虽然不是每个APP都需要,但是随着APP社交化,现在APP上加入聊天界面是很常见的。例如,QQ拥有多样丰富的聊天气泡,全方位满足年轻人标榜个性的需求。而微信只有默认的绿色气泡,朴实无华。对话气泡是漫画放置台词的一种表现手法,对话气泡通常是由线条画成的,气泡的样式会因对白内容而有所变化。我们就来实现一个简单的聊天气泡界面。

4.PNG

开始之前

 在实现聊天气泡界面之前,我们要考虑一下怎么实现。首先要实现的就是一个聊天气泡,区分聊天双方填充不同颜色并且填充留白,接受者和发送者双方的聊天气泡要左右两边分别对齐。气泡大小要随着文字长短变化,文字需要实现自动换行。接下来我们就一步一步的来实现。

聊天列表实现

 首先构建假的聊天内容,创建ChatBubbleList组件,用ListView来包裹我们的聊天气泡。我们创建名为ChatBubble的StatelessWidget气泡组件,结合起来就可以用列表样式显示聊天气泡。实际使用中并不能使用ListView组件,这里只是为了简单,实际中需要使用ListView.builder来动态生成气泡组件。ListView的实现是直接返回最简单的列表结构,粗糙没有修饰,它可以沿一个方向线性排布所有子组件,并且它也支持列表项懒加载。

class ChatBubbleList extends StatelessWidget {
  const ChatBubbleList({super.key});
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: const [
        Padding(
          padding: EdgeInsets.all(12),
        ),
       .....
        ChatBubble(
          text: '。。。。。。!?',
          send: false,
        ),
      ],
    );
  }
}

聊天气泡组件实现

 我们创建名为ChatBubble的StatelessWidget气泡组件,使用DecoratedBox实现聊天气泡,气泡里面包裹text组件显示文字。使用圆形图片剪切组件CircleAvatar显示头像。头像文件放入images文件夹,并在pubspec.yaml文件中设置assets。DecoratedBox可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等。可以设置background参数,在子组件之后绘制内容,即背景装饰。也可以设置参数foreground,在子组件之上绘制,即前景。

  assets:
    - images/

 ChatBubble需要传入text,send两个参数,text就是要显示的文字,用send区分发送者和接受者。

const ChatBubble({
    Key? key,
    required this.text,
    required this.send,
  }) : super(key: key);
  final String text; //要显示的文字
  final bool send; //左右对齐

 根据send来设置DecoratedBox的背景颜色,区分发送者和接受者。

decoration: BoxDecoration(
        color: send //背景颜色
                ? Color.fromARGB(255, 164, 208, 238)
                : Color.fromARGB(255, 153, 231, 169),
         borderRadius: BorderRadius.circular(16),
        ),

 外层使用Row组件来包裹头像CircleAvatar组件和气泡DecoratedBox组件,在DecoratedBox气泡组件中使用Padding组件填充文字四周,使文字能在气泡中有边距的显示。CircleAvatar是一个圆形组件,可以在其中添加背景颜色、背景图像或一些文本。

class ChatBubble extends StatelessWidget {
  const ChatBubble({
    Key? key,
    required this.text,
    required this.send,
  }) : super(key: key);
  final String text; //要显示的文字
  final bool send; //左右对齐
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          //图片圆形剪裁
          radius: 30, //圆形大小
          backgroundColor: Colors.white, //背景颜色设置为白色
          backgroundImage: send
              ? const AssetImage(
                  "images/3.jpeg", //图片
                )
              : const AssetImage(
                  "images/1.jpg", //图片
                ),
        ),
        DecoratedBox(
          decoration: BoxDecoration(
            color: send //背景颜色
                ? Color.fromARGB(255, 164, 208, 238)
                : Color.fromARGB(255, 153, 231, 169),
            borderRadius: BorderRadius.circular(16),
          ),
          child: Padding(
            padding: const EdgeInsets.all(12),
            child: Text(
              text,
              style: const TextStyle(
                fontSize: 14, //字体大小
                color: Color.fromARGB(255, 48, 14, 43),
              ),
            ),
          ),
        )
      ],
    );
  }
}

 效果图如下:

1.PNG

 雏形出现了,但是所有气泡组件都在同一边显示,这显然不是我想要的。

聊天气泡组件左右对齐

 设置Row组件的mainAxisAlignment参数实现左右对齐。在头像组件和气泡组件之间添加Padding组件,这样头像和气泡之间就会有一定距离,看起来更自然一些。

mainAxisAlignment: send ? MainAxisAlignment.start : MainAxisAlignment.end,

 效果图如下:

2.PNG

 气泡这样就左右分别对齐了,但是,女孩子的这部分好像有点不对,头像好像应该显示在右边、文字的后边才对。并且目前文字还不能自动换行,如果文字太长就会报错。

聊天文字自动换行

 我们使用Padding嵌套在最外层,根据发送者或者接收者在两边留白。聊天气泡应在左侧或右侧包含一些填充,以防止它在文本换行时将屏幕铺满。若果文字太长并且没有换行,那么就会直接填充满了屏幕,看起来就不是很美观自然。

Padding(
      padding: EdgeInsets.fromLTRB(
        send ? 4.0 : 50.0,
        2,
        send ? 50.0 : 4.0,
        2,
      ),
      .....

 接下来使用Row组件嵌套Flexible组件实现文字自动换行。Flexible组件可以使Row、Column、Flex等子组件在主轴方向有填充可用空间的能力,但是不强制子组件填充可用空间。Flexible组件作用于单个子项的布局。

class ChatBubble extends StatelessWidget {
  const ChatBubble({
    Key? key,
    required this.text,
    required this.send,
  }) : super(key: key);
  final String text; //要显示的文字
  final bool send; //左右对齐
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(
        send ? 6.0 : 50.0,
        2,
        send ? 50.0 : 6.0,
        2,
      ),
      child: Row(
        mainAxisAlignment:
            send ? MainAxisAlignment.start : MainAxisAlignment.end,
        children: [
          Flexible(
            child: CircleAvatar(
              //图片圆形剪裁
              radius: 25, //圆形大小
              backgroundColor: Colors.white, //背景颜色设置为白色
              backgroundImage: send
                  ? const AssetImage(
                      "images/3.jpeg", //图片
                    )
                  : const AssetImage(
                      "images/1.jpg", //图片
                    ),
            ),
          ),
          const Padding(
            padding: EdgeInsets.fromLTRB(2, 0, 2, 0),
          ),
          Flexible(
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: send //背景颜色
                    ? Color.fromARGB(255, 164, 208, 238)
                    : Color.fromARGB(255, 153, 231, 169),
                borderRadius: BorderRadius.circular(16),
              ),
              child: Padding(
                padding: const EdgeInsets.all(12),
                child: Text(
                  text,
                  style: const TextStyle(
                    fontSize: 14, //字体大小
                    color: Color.fromARGB(255, 48, 14, 43),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 效果图如下:

3.PNG

总结

 我们简单的实现了一个聊天界面UI,可以显示头像,文字可以自动换行,发送者与接收者聊天气泡左右两边分别对齐,并且设置了不同的背景颜色。目前为止基本满足了一个社交App的基本要求。即时通讯在社交生活中扮演着重要的角色,从早期的文字聊天到图片音频的发送,演变到现如今的即时语音与视频传输,即时通讯软件得到了迅速的发展,QQ、微信等社交软件使用人数不断增加。即时通讯在办公领域的应用也极为广泛,例如钉钉会议等软件都具有聊天功能,即时通讯软件能够让企业中各项工作第一时间汇总,各部门工作人员可以轻松地相互交流工作。一个实际使用的聊天UI肯定需要更多的功能,我们后续开发的时候可以在此基础上进一步优化,添加更多需要的功能。