likes
comments
collection
share

flutter chat UI 聊天界面实战

作者站长头像
站长
· 阅读数 19

flutter chat UI 聊天界面实战

 上一篇笔记完成了一个登陆界面的花架子,只能远观,不能使用,这篇再试一下一个聊天界面UI,依旧是花架子,哈哈。

寻找聊天界面模板

 依旧先找一个好看的模板来照猫画虎吧。找了半天,最终决定用下边这个ui当做模板,个人感觉挺好看的的。

 flutter chat UI 聊天界面实战

UI实现

 话不多说,开始着手实现这个模板。首先分析一下模板布局和元素,看来看去,想来想去,对于我来说这个模板还是有点复杂,还是简化的实现吧。

 将模板分成两部分、四个模块来实现,最右边的一竖条感觉有点难看,直接砍掉他,把这部分的按钮放在聊天框的上部分来实现。

 flutter chat UI 聊天界面实战

两部分拆分

 首先,依旧是新建项目并运行,实现一个空白模板,和上一篇login UI实现的一样,先使用Row水平布局组件,将整个白板分割成Leftbody、Rightbody两部分。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, //去掉右上角debug标识
      theme: ThemeData(
        //主题设置
        primarySwatch: Colors.blue,
      ),
      home: const SelectionArea(
        //子组件支持文字选定 3.3新特性
        child: Scaffold(
          //子组件
          body: MyAppbody(),
        ),
      ),
    );
  }
}

class MyAppbody extends StatelessWidget {
  const MyAppbody({super.key});
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        //水平布局
        children: const <Widget>[
          //子组件
          Expanded(
            //空间占比组件
            flex: 1, //左侧空间占比
            child: Leftbody(), //左侧布局
          ),
          Expanded(
            flex: 2, //右侧空间占比
            child: Rightbody(), //右侧布局
          ),
        ],
      ),
    );
  }
}

Leftbody实现

 在lib目录下新建leftbody文件夹,在此文件夹下新建leftbody.dart,将左侧部分所有代码都写在这个文件中。分析左侧部分布局,外层先是一个竖向布局,然后竖向布局里面依次放置图标、用户、好友列表。

import 'package:flutter/material.dart';

class Leftbody extends StatelessWidget {
  const Leftbody({super.key});
  @override
  Widget build(BuildContext context) {
    return Column(
      children: const <Widget>[
        Expanded(
          //空间占比组件
          flex: 1, //空间占比
          child: Padding(
            padding: EdgeInsets.fromLTRB(0, 0, 0, 0), //填充
            child: Logo(), //logo实现
          ),
        ),
        Expanded(
          //空间占比组件
          flex: 1, //空间占比
          child: Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
            //child: User(), //User
          ),
        ),
        Expanded(
          //空间占比组件
          flex: 1, //空间占比
          child: Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
            //child: Friends(), //Friends
          ),
        ),
      ],
    );
  }
}
招牌logo部分

 logo部分是一个图片和一段文字构成,我我们就横向放置一个图片组件和一个文字组件来实现,图片利用CircleAvatar进行圆角切割,文字设置为粗体。

class Logo extends StatelessWidget {
  const Logo({super.key});
  @override
  Widget build(BuildContext context) {
    return Row(
      children: const <Widget>[
        CircleAvatar(
          //图片圆形剪裁
          radius: 20, //圆形直径,(半径)?
          backgroundColor: Colors.white, //背景颜色设置为白色
          backgroundImage: AssetImage(
            "images/1.png",//logo图片
          ),
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
        ),
        Text(
          "Messenger",
          style: TextStyle(
            fontSize: 20, //字体大小
            fontWeight: FontWeight.bold, //字体加粗
          ),
        ),
      ],
    );
  }
}

 效果:

 flutter chat UI 聊天界面实战

分割线

 在logo下边有一个分割线,我们用Divider实现,可以设置它的左右缩进长度和颜色。

Divider(height: 1.0,indent: 60.0,endIndent:60.0,color: Colors.grey,),//分割线

 效果: 4.png

用户信息展示部分

 这部分是使用者自己的信息展示,包括头像,主标题名字,副标题介绍,在线情况,后边还有一个设置图标按钮。先实现一个带头像和通知圆点的个人信息展示模块,这里简化实现了,去掉了Online展示模块,因为我不会。。。

 使用ListTile组件实现列表,头部使用Badge插件实现小圆点通知,通过position设置小圆点显示位置,通过badgeColor设置圆点颜色,通过borderSide设置圆点白色边框,头像显示依然使用CircleAvatar组件,尾部用一个不可点击的图标装饰,当然也可以放一个带图标按钮。

class User extends StatelessWidget {
  const User({super.key});
  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: Badge(
        //头部部件
        //通知小圆点
        badgeColor: Colors.green, //小圆点颜色
        position: const BadgePosition(
            start: 35, top: 35, end: 0, bottom: 0), //小圆点显示位置
        borderSide:
            const BorderSide(color: Colors.white, width: 1.5), //外层白色圆圈框框
        child: const CircleAvatar(
          //图片圆形剪裁
          radius: 25, //圆形直径,(半径)?
          backgroundColor: Colors.white, //背景颜色设置为白色
          backgroundImage: AssetImage(
            "images/1.jpg", //图片
          ),
        ),
      ),
      title: const Text(
        "George xiaolan",
        style: TextStyle(
          fontSize: 15, //字体大小
          fontWeight: FontWeight.bold, //字体加粗
        ),
      ), //标题
      subtitle: const Text(
        "Google",
        style: TextStyle(
          fontSize: 10, //字体大小
          fontWeight: FontWeight.bold, //字体加粗
        ),
      ),
      trailing: const Icon(Icons.settings), //尾部图标
    );
  }
}

 效果:

 flutter chat UI 聊天界面实战

搜索框

 对照模板,简化处理,略过Active Chats,直接实现好友搜索框。我使用TextField实现搜索框,使用prefixIcon、suffixIcon实现头尾搜索图标和叉叉图标,通过border设置圆角显示,通过fillColor设置背景为灰色同时设置透明度。hintText可以设置提示文字。这样一个简单的搜索框就实现了。

class SearchWidget extends StatefulWidget {
  final double? height; // 高度
  final double? width; // 宽度
  final String? hintText; // 输入提示
  final ValueChanged<String>? onEditingComplete; // 编辑完成的事件回调

  const SearchWidget(
      {Key? key,
      this.height,
      this.width,
      this.hintText,
      this.onEditingComplete})
      : super(key: key);

  @override
  State<SearchWidget> createState() => _SearchWidgetState();
}

class _SearchWidgetState extends State<SearchWidget> {
  var controller = TextEditingController();

  @override
  void initState() {
    super.initState();
  }

  /// 清除查询关键词
  clearKeywords() {
    controller.text = "";
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constrains) {
       return  TextField(
          controller: controller,
          decoration: InputDecoration(
            prefixIcon: const Icon(Icons.search),//头部搜索图标
            filled: true,
            fillColor: Colors.grey.withAlpha(50), // 设置输入框背景色为灰色,并设置透明度
            hintText: "Search people",
            hintStyle: const TextStyle(color: Colors.grey, fontSize: 14),
            contentPadding: const EdgeInsets.only(bottom: 10),
            border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(15),//圆角边框
                borderSide: BorderSide.none),
            suffixIcon: IconButton(//尾部叉叉图标
                  icon: const Icon(
                    Icons.close,
                    size: 17,
                  ),
                  onPressed: clearKeywords,//清空操作
                  splashColor: Theme.of(context).primaryColor,
                )
          ),
        );
    });
  }
}

 效果:

 flutter chat UI 聊天界面实战

好友列表

 接着实现好友列表。使用ListView包裹ListTile实现列表。ListTile基本上可以实现很多功能,包括头像、标题、子标题,需要特别关注的是上线状态小圆圈和消息提示小圆圈的实现,我们依旧使用Badge插件实现。为了简单起见,并且自己能力有限,所以好友列表使用若干ListTile实现,这种方式只适合实现一个花架子,如果真实使用,这样肯定是行不通的。

class Friends extends StatelessWidget {
  const Friends({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      scrollDirection: Axis.vertical,
      children: const <Widget>[
        Friends1(),
        Friends3(),
        Friends4(),
        Friends5(),
        Friends6(),
        Friends7(),
        Friends8(),
        Friends9(),
      ],
    );
  }
}

class Friends1 extends StatelessWidget {
  const Friends1({super.key});
  @override
  Widget build(BuildContext context) {
    return ListTile(
      onTap: () {},
      leading: Badge(
        //头部部件
        //通知小圆点
        badgeColor: Colors.green, //小圆点颜色
        position: const BadgePosition(
            start: 35, top: 35, end: 0, bottom: 0), //小圆点显示位置
        borderSide:
            const BorderSide(color: Colors.white, width: 1.5), //外层白色圆圈框框
        child: const CircleAvatar(
          //图片圆形剪裁
          radius: 25, //圆形直径,(半径)?
          backgroundColor: Colors.white, //背景颜色设置为白色
          backgroundImage: AssetImage(
            "images/2.jpg", //图片
          ),
        ),
      ),
      title: const Text(
        "Facebo anaolan",
        style: TextStyle(
          fontSize: 15, //字体大小
          fontWeight: FontWeight.bold, //字体加粗
        ),
      ), //标题
      subtitle: const Text(
        "Facebow",
        style: TextStyle(
          fontSize: 10, //字体大小
          fontWeight: FontWeight.bold, //字体加粗
        ),
      ),
      trailing: Badge(
        //尾部部件
        //通知小圆点
        //  padding: EdgeInsets.all(2),
        badgeContent: const Text(
          '3',
          style: TextStyle(
            fontSize: 10, //字体大小
            // fontWeight: FontWeight.bold, //字体加粗
            color: Colors.white,
          ),
        ),
        badgeColor: Colors.green, //小圆点颜色
        borderRadius: BorderRadius.circular(10),
        position: const BadgePosition(
            start: 10, top: 10, end: 0, bottom: 0), //小圆点显示位置
        borderSide: const BorderSide(color: Colors.white, width: 1), //外层白色圆圈框框
      ), //尾部图标
    );
  }
}

 效果:

 flutter chat UI 聊天界面实战

总结

 这个项目暂时先实现到这里。下边是模板和自己的效果图,不得不说差距还是很大的,并且只能看看,不能实际使用,自己的差距还是很大的,后边还要继续学习。还有很多坑需要实现,包括列表的动态实现,时间戳显示,搜索栏实现条目搜索,上线下线图标变化,在以后的学习中再慢慢补课吧。

 flutter chat UI 聊天界面实战

 flutter chat UI 聊天界面实战