前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【10】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时

【10】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时

原创
作者头像
卓伊凡
发布2025-02-05 18:06:14
发布2025-02-05 18:06:14
16100
代码可运行
举报
文章被收录于专栏:其他相关技术其他相关技术
运行总次数:0
代码可运行

【10】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

章节内容【10】

【10】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍

开发背景

背景说明要提一点:我们所有的开发耗尽2个月的时间,目前只是整合与记录并且呈现过程,大家不要想的太简单,自己试试就知道了哈,而不是你们以为的很快很简单,这点请必须要知道。

闲话不多,开源仓库地址,可以观摩已经写好的代码:

https://gitee.com/youyacao/ff-flutter

demo下载

https://www.youyacao.cn/freefirend

更新代码文件和日志文件-gitee可见

·完善了聊天即时通讯整体页面 ·完善了即时通讯聊天组件 ·完善了即时通讯切换组件 ·完善了即时通讯聊天朋友选择 ·完善了vip打开的vip详细页面

代码语言:javascript
代码运行次数:0
复制
assets/images/msg_friend_icon.png                  | Bin 0 -> 6133 bytes
 assets/images/msg_note_icon.png                    | Bin 0 -> 4657 bytes
 assets/images/vip_diamond.png                      | Bin 0 -> 19157 bytes
 assets/images/vip_gold.png                         | Bin 0 -> 18020 bytes
 assets/images/vip_regular.png                      | Bin 0 -> 13222 bytes
 lib/routes/app_pages.dart                          |   6 ++
 lib/routes/app_routes.dart                         |   4 +
 lib/screens/account/widgets/open_vip.dart          |  78 ++++++++------
 lib/screens/index.dart                             |   2 +-
 lib/screens/message_screen.dart                    |  16 ---
 lib/screens/messages/index.dart                    |   9 ++
 .../messages/widgets/chat_section/index.dart       |  37 +++++++
 .../widgets/chat_section/widgets/chat_item.dart    |  82 +++++++++++++++
 .../widgets/chat_section/widgets/chat_list.dart    |  90 ++++++++++++++++
 .../widgets/chat_section/widgets/chat_tab_bar.dart |  42 ++++++++
 lib/screens/messages/widgets/friend_section.dart   |  81 +++++++++++++++
 lib/screens/messages/widgets/message_header.dart   |  56 ++++++++++
 .../messages/widgets/message_screen_widget.dart    |  30 ++++++
 .../messages/widgets/notification_item.dart        |  56 ++++++++++
 lib/screens/vip/index.dart                         |  21 ++++
 lib/screens/vip/widgets/member_combo.dart          | 114 +++++++++++++++++++++
 lib/screens/vip/widgets/vip_header.dart            |  46 +++++++++
 lib/screens/vip/widgets/vip_user_info.dart         |  47 +++++++++
 pubspec.lock                                       |  46 ++++-----
 24 files changed, 789 insertions(+), 74 deletions(-)
 create mode 100644 assets/images/msg_friend_icon.png
 create mode 100644 assets/images/msg_note_icon.png
 create mode 100644 assets/images/vip_diamond.png
 create mode 100644 assets/images/vip_gold.png
 create mode 100644 assets/images/vip_regular.png
 delete mode 100644 lib/screens/message_screen.dart
 create mode 100644 lib/screens/messages/index.dart
 create mode 100644 lib/screens/messages/widgets/chat_section/index.dart
 create mode 100644 lib/screens/messages/widgets/chat_section/widgets/chat_item.dart
 create mode 100644 lib/screens/messages/widgets/chat_section/widgets/chat_list.dart
 create mode 100644 lib/screens/messages/widgets/chat_section/widgets/chat_tab_bar.dart
 create mode 100644 lib/screens/messages/widgets/friend_section.dart
 create mode 100644 lib/screens/messages/widgets/message_header.dart
 create mode 100644 lib/screens/messages/widgets/message_screen_widget.dart
 create mode 100644 lib/screens/messages/widgets/notification_item.dart
 create mode 100644 lib/screens/vip/index.dart
 create mode 100644 lib/screens/vip/widgets/member_combo.dart
 create mode 100644 lib/screens/vip/widgets/vip_header.dart
 create mode 100644 lib/screens/vip/widgets/vip_user_info.dart

实战开始

这里上一篇很多人 问那些图片怎么弄的,看清楚

代码语言:javascript
代码运行次数:0
复制
create mode 100644 assets/images/vip_gold.png
 create mode 100644 assets/images/vip_regular.png
 delete mode 100644 lib/screens/message_screen.dart
 create mode 100644 lib/screens/messages/index.dart

这类型,说明没有仔细看第一篇,第一篇详细讲述了我们的资源文件要存放至 assets 资源文件夹对应目录,在第二篇的时候还做了目录框架规划,这里请注意了。

即时通讯和直播sdk的准备以及有无ui集成的区别

首先本项目已经确定是采用腾讯云sdk,因此我们登陆腾讯云,我们以直播sdk来区分介绍信息,我们登陆直播sdk管理处

我们可以看到现在的直播lisence是可以免费创建测试的,以前是创建测试也是收费的,这点须知,这里我们先跳过 先来讲有ui集成和无ui集成

有UI集成

这个地址就是有关腾讯云直播SDK的技术文档地址了: https://cloud.tencent.com/document/product/454/72057 这个就是有UI集成的方案,有UI集成是TUIkit方案,大白话就是这个方案是腾讯云官方提供的,也是比较好用的。 TUIkit 是腾讯云音视频团队结合业内主流的音视频场景,提炼出的开源解决方案,包含视频通话组件、直播组件、视频房间组件等多个客户端音视频组件,可以帮助开发者快速搭建诸如通话、客服、直播、语聊、教育等场景解决方案。

我们点击继续查看组件详细情况,那么也就是说这个带ui的集成sdk方案的界面基本也就是这个样子了。

有ui的集成方案的组件叫做TUIPusher 组件,

TUIPusher 组件是一套开源的、完整的视频直播互动推流组件,它基于腾讯云 直播 Live SDK 和 即时通信 IM SDK ,实现直播推流,直播 PK 等功能,同时支持弹幕、点赞、美颜等外挂插件,使用 TUIPusher 组件您可以快速搭建诸如秀场直播、电商直播等场景化解决方案。

优势:集成速度快,降低开发成本和周期 弊端:只能采用已经做好的这个默认的UI方案。

无UI集成

再看无ui集成方案,

说明实例部分

无ui集成相对复杂,难度几何增长,因此腾讯云官方为了考虑技术团队开发的成本提供了官方demo可以下载

为了帮助您更好地上手移动端直播 APP 的搭建工作,我们推出了腾讯云 MLVB-API-Example Demo,您可以根据下列操作指引快速跑通 Demo。 本文主要介绍如何快速运行腾讯云 MLVB-API-Example(Android)。

提供了原生demo,无ui集成相当于只能参考每个地方的接口,把所有的类和对象也有提供给你。

这是我们关于项目的界面,因此我们是无UI集成。

那么综上所述我们的项目是无UI集成,我们的难度更高,工作量更大,在现实商业项目中研发费用也更高,因此每个页面都是独立要先写的。

其他部分SDK以此类推,举一反三,其中本项目中要用到的SDK有,实时音视频sdk,即时通讯sdk,直播sdk,国际版短信发送SDK,介绍完毕,我们来看书写的代码。

代码书写

主要增加的代码在message 部分,也就是用来做聊天的,

chat_item.dart 聊天框

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class ChatItem extends StatelessWidget {
  final String name;
  final String message;
  final String time;
  final bool hasNewMessage;
  final bool isFirst;

  const ChatItem({
    required this.name,
    required this.message,
    required this.time,
    this.hasNewMessage = false,
    this.isFirst = false,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(
        left: 30.w,
        right: 30.w,
        top: isFirst ? 20.h : 20.h,
        bottom: 20.h,
      ),
      child: Row(
        children: [
          ClipRRect(
            borderRadius: BorderRadius.circular(36.r),
            child: Image.asset(
              'assets/images/girl.png',
              width: 72.w,
              height: 72.h,
              fit: BoxFit.cover,
            ),
          ),
          SizedBox(width: 24.w),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      name,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 32.sp,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      time,
                      style: TextStyle(
                        color: Colors.grey,
                        fontSize: 26.sp,
                      ),
                    ),
                  ],
                ),
                SizedBox(height: 8.h),
                Text(
                  message,
                  style: TextStyle(
                    color:
                        hasNewMessage ? const Color(0xFFFF3034) : Colors.grey,
                    fontSize: 28.sp,
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

chat_list.dart 聊天列表

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'chat_item.dart';

class ChatList extends StatelessWidget {
  final bool isFriend;

  const ChatList({required this.isFriend});

  @override
  Widget build(BuildContext context) {
    final List<Map<String, dynamic>> chatData = isFriend
        ? [
            {
              'name': 'ANNA',
              'message': 'There is a new message',
              'time': '15:23',
              'hasNewMessage': true,
            },
            {
              'name': 'ANNA',
              'message': 'hello!',
              'time': '15:23',
              'hasNewMessage': false,
            },
            {
              'name': 'Lily',
              'message': 'hello!',
              'time': '15:23',
              'hasNewMessage': false,
            },
            {
              'name': 'Lily',
              'message': 'hello!',
              'time': '15:23',
              'hasNewMessage': true,
            },
          ]
        : [
            {
              'name': 'Sarah',
              'message': 'Nice to meet you!',
              'time': '16:30',
              'hasNewMessage': true,
            },
            {
              'name': 'Emma',
              'message': 'How are you?',
              'time': '16:28',
              'hasNewMessage': false,
            },
            {
              'name': 'Sophie',
              'message': 'I like your photos!',
              'time': '16:25',
              'hasNewMessage': true,
            },
            {
              'name': 'Olivia',
              'message': 'Can we be friends?',
              'time': '16:20',
              'hasNewMessage': false,
            },
          ];

    return ListView.separated(
      shrinkWrap: true,
      physics: const ClampingScrollPhysics(),
      padding: EdgeInsets.only(top: 10.h),
      itemCount: chatData.length,
      separatorBuilder: (context, index) => Padding(
        padding: EdgeInsets.symmetric(horizontal: 30.w),
        child: Divider(
          height: 1.h,
          color: Colors.white.withOpacity(0.1),
        ),
      ),
      itemBuilder: (context, index) {
        final chat = chatData[index];
        return ChatItem(
          name: chat['name'],
          message: chat['message'],
          time: chat['time'],
          hasNewMessage: chat['hasNewMessage'],
          isFirst: index == 0,
        );
      },
    );
  }
}

这段代码定义了一个名为 ChatList 的无状态小部件,用于显示聊天列表。根据 isFriend 参数的不同,展示不同的聊天数据。每个聊天项通过 ChatItem 小部件展示,包含名称、消息、时间和是否有新消息的标志。

控制流图

代码语言:javascript
代码运行次数:0
复制
flowchart TD
    A[开始] --> B{判断 isFriend}
    B -->|是| C[使用朋友聊天数据]
    B -->|否| D[使用非朋友聊天数据]
    C --> E[创建 ListView]
    D --> E
    E --> F[遍历聊天数据]
    F --> G{是否为第一个元素}
    G -->|是| H[设置 isFirst 为 true]
    G -->|否| I[设置 isFirst 为 false]
    H --> J[生成 ChatItem]
    I --> J
    J --> K[返回 ChatItem]
    K --> F

chat_tab_bar 聊天页面的切换

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class ChatTabBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.centerLeft,
      child: Theme(
        data: ThemeData(
          tabBarTheme: TabBarTheme(
            labelPadding:
                EdgeInsets.symmetric(horizontal: 30.w, vertical: 10.h),
            tabAlignment: TabAlignment.start,
          ),
        ),
        child: TabBar(
          isScrollable: true,
          indicatorWeight: 4.h,
          indicatorSize: TabBarIndicatorSize.label,
          indicatorColor: const Color(0xFFFF3034),
          labelColor: Colors.white,
          unselectedLabelColor: Colors.grey,
          labelStyle: TextStyle(
            fontSize: 32.sp,
            fontWeight: FontWeight.bold,
          ),
          unselectedLabelStyle: TextStyle(
            fontSize: 32.sp,
            fontWeight: FontWeight.normal,
          ),
          dividerColor: Colors.transparent,
          // labelPadding: EdgeInsets.symmetric(horizontal: 30.w),
          tabs: const [
            Tab(text: 'Friend'),
            Tab(text: 'Stranger'),
          ],
        ),
      ),
    );
  }
}

index.dart 聊天首页

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:ff_flutter/screens/messages/widgets/chat_section/widgets/chat_tab_bar.dart';
import 'package:ff_flutter/screens/messages/widgets/chat_section/widgets/chat_list.dart';

class ChatSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 30.h, left: 30.w, right: 30.w),
      decoration: BoxDecoration(
        color: const Color(0xFF151313),
        borderRadius: BorderRadius.circular(30.r),
      ),
      child: DefaultTabController(
        length: 2,
        child: SizedBox(
          height: 1000.h,
          child: Column(
            children: [
              ChatTabBar(),
              Expanded(
                child: TabBarView(
                  physics: const NeverScrollableScrollPhysics(),
                  children: const [
                    ChatList(isFriend: true),
                    ChatList(isFriend: false),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

聊天朋友

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class FriendSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(30.w, 50.h, 30.w, 0),
      child: Container(
        height: 112.h,
        decoration: BoxDecoration(
          color: const Color(0xFF151313),
          borderRadius: BorderRadius.circular(30.r),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Row(
              children: [
                SizedBox(width: 32.w),
                Image.asset(
                  'assets/images/msg_friend_icon.png',
                  width: 72.w,
                  height: 72.h,
                ),
                SizedBox(width: 24.w),
                Row(
                  children: [
                    Text(
                      'My friend',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 28.sp,
                        fontWeight: FontWeight.normal,
                      ),
                    ),
                    SizedBox(width: 16.w),
                    Text(
                      '(30)',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 28.sp,
                      ),
                    ),
                  ],
                ),
              ],
            ),
            Row(
              children: [
                Container(
                  padding:
                      EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
                  decoration: BoxDecoration(
                    color: const Color(0xFFFF3034),
                    borderRadius: BorderRadius.circular(24.r),
                  ),
                  child: Text(
                    'new',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 24.sp,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                SizedBox(width: 16.w),
                Icon(
                  Icons.chevron_right,
                  color: Colors.white,
                  size: 48.sp,
                ),
                SizedBox(width: 32.w),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

notification_item.dart

消息通知

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class NotificationItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(30.w, 30.h, 30.w, 0),
      child: Container(
        height: 128.h,
        decoration: BoxDecoration(
          color: const Color(0xFF151313),
          borderRadius: BorderRadius.circular(30.r),
        ),
        child: Padding(
          padding:
              EdgeInsets.only(left: 30.w, right: 20.w, top: 20.h, bottom: 20.h),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Image.asset(
                'assets/images/msg_note_icon.png',
                width: 72.w,
                height: 72.h,
              ),
              SizedBox(width: 24.w),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      '15:23',
                      style: TextStyle(
                        color: Colors.grey,
                        fontSize: 26.sp,
                      ),
                    ),
                    SizedBox(height: 8.h),
                    Text(
                      'ANNA followed you',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 28.sp,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

还有几个小的不看了就,在下面是vip开通

代码语言:javascript
代码运行次数:0
复制
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class MemberCombo extends StatefulWidget {
  @override
  State<MemberCombo> createState() => _MemberComboState();
}

class _MemberComboState extends State<MemberCombo> {
  int selectedIndex = 0;

  final List<Map<String, dynamic>> memberTypes = [
    {
      'title': 'Regular member',
      'icon': 'assets/images/vip_regular.png',
      'darkColor': const Color(0xFF393939),
    },
    {
      'title': 'Gold Membership',
      'icon': 'assets/images/vip_gold.png',
      'darkColor': const Color(0xFF393939),
    },
    {
      'title': 'Diamond',
      'icon': 'assets/images/vip_diamond.png',
      'darkColor': const Color(0xFF393939),
    },
  ];

  final Gradient selectedGradient = const LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Color(0xFFECD29F),
      Color(0xFFE1BA7F),
    ],
  );

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 60.h),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: EdgeInsets.only(left: 30.w, bottom: 38.h),
            child: Text(
              'Member Combo',
              style: TextStyle(
                color: Colors.white,
                fontSize: 40.sp,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          SizedBox(
            height: 186.h,
            child: ListView.builder(
              scrollDirection: Axis.horizontal,
              padding: EdgeInsets.symmetric(horizontal: 30.w),
              itemCount: memberTypes.length,
              itemBuilder: (context, index) {
                final isSelected = selectedIndex == index;
                return GestureDetector(
                  onTap: () {
                    setState(() {
                      selectedIndex = index;
                    });
                  },
                  child: Container(
                    width: 296.w,
                    margin: EdgeInsets.only(right: 20.w),
                    decoration: BoxDecoration(
                      gradient: isSelected ? selectedGradient : null,
                      color:
                          isSelected ? null : memberTypes[index]['darkColor'],
                      borderRadius: BorderRadius.circular(30.r),
                    ),
                    child: Stack(
                      children: [
                        Positioned(
                          left: 30.w,
                          top: 30.h,
                          child: Image.asset(
                            memberTypes[index]['icon'],
                            width: 48.w,
                            height: 48.h,
                          ),
                        ),
                        Positioned(
                          left: 30.w,
                          bottom: 30.h,
                          child: Text(
                            memberTypes[index]['title'],
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 32.sp,
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

核心在这个部分,

这段代码实现了一个会员组合选择界面,用户可以通过点击不同的会员类型卡片来选择会员等级。界面包含一个标题和一个水平滚动的会员卡片列表,每个卡片显示会员图标和名称。选中的卡片会高亮显示。

控制流图

mermaid

代码语言:javascript
代码运行次数:0
复制
flowchart TD
    A[初始化] --> B[构建界面]
    B --> C{是否点击卡片}
    C -->|Yes| D[更新选中索引]
    D --> E[重新构建界面]
    C -->|No| F[保持当前状态]

我们在模拟器来看看效果:

聊天页面

开通vip的页面

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【10】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 章节内容【10】
  • 开发背景
  • demo下载
  • 更新代码文件和日志文件-gitee可见
  • 实战开始
    • 即时通讯和直播sdk的准备以及有无ui集成的区别
      • 有UI集成
      • 无UI集成
    • 代码书写
  • 控制流图
  • 控制流图
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档