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

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

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

章节内容【11】

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

开发背景

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

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

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

demo下载

https://www.youyacao.cn/freefirend

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

·完善了vip购买页面的其他功能
·增加了用户邀请码页面
·增加了申请主播资料填写页面
·增加了安全中心介绍页
·增加了帮助中心介绍页
·创建腾讯云直播SDK相关信息
·创建即时通讯sdk相关信息

assets/images/invite_box.png                       | Bin 0 -> 340684 bytes
 assets/images/invite_friend_icon.png               | Bin 0 -> 13944 bytes
 assets/images/invite_gold_coin.png                 | Bin 0 -> 17238 bytes
 assets/images/vip_advance.png                      | Bin 0 -> 10671 bytes
 assets/images/vip_all_videos.png                   | Bin 0 -> 17366 bytes
 assets/images/vip_auto_renew.png                   | Bin 0 -> 6721 bytes
 assets/images/vip_hd.png                           | Bin 0 -> 15988 bytes
 assets/images/vip_no_ads.png                       | Bin 0 -> 16945 bytes
 lib/routes/app_pages.dart                          |  30 ++++
 lib/routes/app_routes.dart                         |   5 +
 lib/screens/account/widgets/menu_list.dart         |  87 ++++++----
 lib/screens/account/widgets/user_info.dart         |  27 +--
 lib/screens/anchor_apply/index.dart                |  90 ++++++++++
 .../anchor_apply/widgets/anchor_apply_form.dart    | 155 +++++++++++++++++
 lib/screens/help_center/index.dart                 |  75 ++++++++
 .../help_center/widgets/help_menu_item.dart        |  45 +++++
 lib/screens/invite_friends/index.dart              |  22 +++
 .../invite_friends/widgets/invite_card.dart        | 188 +++++++++++++++++++++
 .../invite_friends/widgets/invite_header.dart      |  41 +++++
 lib/screens/personal_data/index.dart               |  33 ++++
 .../personal_data/widgets/personal_data_form.dart  | 147 ++++++++++++++++
 lib/screens/security_center/index.dart             |  79 +++++++++
 .../widgets/security_menu_item.dart                |  45 +++++
 lib/screens/vip/index.dart                         |  27 ++-
 lib/screens/vip/widgets/member_benefits.dart       |  78 +++++++++
 lib/screens/vip/widgets/member_combo.dart          |   4 +-
 lib/screens/vip/widgets/vip_purchase.dart          |  90 ++++++++++
 27 files changed, 1218 insertions(+), 50 deletions(-)
 create mode 100644 assets/images/invite_box.png
 create mode 100644 assets/images/invite_friend_icon.png
 create mode 100644 assets/images/invite_gold_coin.png
 create mode 100644 assets/images/vip_advance.png
 create mode 100644 assets/images/vip_all_videos.png
 create mode 100644 assets/images/vip_auto_renew.png
 create mode 100644 assets/images/vip_hd.png
 create mode 100644 assets/images/vip_no_ads.png
 create mode 100644 lib/screens/anchor_apply/index.dart
 create mode 100644 lib/screens/anchor_apply/widgets/anchor_apply_form.dart
 create mode 100644 lib/screens/help_center/index.dart
 create mode 100644 lib/screens/help_center/widgets/help_menu_item.dart
 create mode 100644 lib/screens/invite_friends/index.dart
 create mode 100644 lib/screens/invite_friends/widgets/invite_card.dart
 create mode 100644 lib/screens/invite_friends/widgets/invite_header.dart
 create mode 100644 lib/screens/personal_data/index.dart
 create mode 100644 lib/screens/personal_data/widgets/personal_data_form.dart
 create mode 100644 lib/screens/security_center/index.dart
 create mode 100644 lib/screens/security_center/widgets/security_menu_item.dart
 create mode 100644 lib/screens/vip/widgets/member_benefits.dart
 create mode 100644 lib/screens/vip/widgets/vip_purchase.dart

实战开始

页面结果

先看看结果

个人中心的

邀请页面


直播页面


帮助中心页面以及安全中心页面 ,类似就一个代替

购买vip页面完善。

代码部分

先看个人中心页面的变化:

personal_data_form.dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class PersonalDataForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 60.w),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SizedBox(height: 60.h),
            _buildLabel('Profile picture'),
            SizedBox(height: 20.h),
            // 头像选择区域
            Container(
              width: 140.w,
              height: 140.h,
              decoration: BoxDecoration(
                color: const Color(0xFF393939),
                borderRadius: BorderRadius.circular(20.r),
              ),
              child: Center(
                child: Icon(
                  Icons.add,
                  color: Colors.white,
                  size: 48.sp,
                ),
              ),
            ),
            SizedBox(height: 40.h),
            _buildLabel('Name'),
            SizedBox(height: 20.h),
            _buildTextField('Name'),
            SizedBox(height: 40.h),
            _buildLabel('Date of birth'),
            SizedBox(height: 20.h),
            _buildTextField('Date of birth', suffixIcon: Icons.calendar_today),
            SizedBox(height: 40.h),
            _buildLabel('Gender'),
            SizedBox(height: 20.h),
            _buildDropdown('Choose your gender'),
            SizedBox(height: 40.h),
            _buildLabel('Area'),
            SizedBox(height: 20.h),
            _buildDropdown('Choose your region'),
            SizedBox(height: 60.h),
            _buildConfirmButton(),
          ],
        ),
      ),
    );
  }
  Widget _buildLabel(String text) {
    return Text(
      text,
      style: TextStyle(
        color: Colors.white,
        fontSize: 32.sp,
        fontWeight: FontWeight.w500,
      ),
    );
  }
  Widget _buildTextField(String hint, {IconData? suffixIcon}) {
    return Container(
      height: 100.h,
      decoration: BoxDecoration(
        color: const Color(0xFF393939),
        borderRadius: BorderRadius.circular(20.r),
      ),
      child: TextField(
        style: TextStyle(
          color: Colors.white,
          fontSize: 32.sp,
        ),
        decoration: InputDecoration(
          hintText: hint,
          hintStyle: TextStyle(
            color: Colors.grey,
            fontSize: 32.sp,
          ),
          border: InputBorder.none,
          contentPadding: EdgeInsets.symmetric(horizontal: 30.w),
          suffixIcon: suffixIcon != null
              ? Icon(
                  suffixIcon,
                  color: Colors.grey,
                  size: 48.sp,
                )
              : null,
        ),
      ),
    );
  }
  Widget _buildDropdown(String hint) {
    return Container(
      height: 100.h,
      padding: EdgeInsets.symmetric(horizontal: 30.w),
      decoration: BoxDecoration(
        color: const Color(0xFF393939),
        borderRadius: BorderRadius.circular(20.r),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            hint,
            style: TextStyle(
              color: Colors.grey,
              fontSize: 32.sp,
            ),
          ),
          Icon(
            Icons.keyboard_arrow_down,
            color: Colors.grey,
            size: 48.sp,
          ),
        ],
      ),
    );
  }
  Widget _buildConfirmButton() {
    return Container(
      width: double.infinity,
      height: 100.h,
      decoration: BoxDecoration(
        color: const Color(0xFFE56389),
        borderRadius: BorderRadius.circular(50.r),
      ),
      child: Center(
        child: Text(
          'Confirm Save',
          style: TextStyle(
            color: Colors.white,
            fontSize: 36.sp,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

这段代码定义了一个名为 PersonalDataForm 的无状态小部件,用于显示个人资料表单。表单包含头像选择、姓名、出生日期、性别、地区输入框及确认按钮。各个输入项通过 _buildLabel、_buildTextField、_buildDropdown 和 _buildConfirmButton 方法构建。

控制流图

flowchart TD
    A[开始] --> B[创建 SingleChildScrollView]
    B --> C[创建 Padding]
    C --> D[创建 Column]
    D --> E{添加子组件}
    E -->|Profile picture 标签| F[创建 _buildLabel]
    F --> G[创建 SizedBox]
    G --> H[创建 Container 头像选择区域]
    H --> I[创建 SizedBox]
    I --> J[创建 Name 标签]
    J --> K[创建 SizedBox]
    K --> L[创建 Name 输入框]
    L --> M[创建 SizedBox]
    M --> N[创建 Date of birth 标签]
    N --> O[创建 SizedBox]
    O --> P[创建 Date of birth 输入框]
    P --> Q[创建 SizedBox]
    Q --> R[创建 Gender 标签]
    R --> S[创建 SizedBox]
    S --> T[创建 Gender 下拉框]
    T --> U[创建 SizedBox]
    U --> V[创建 Area 标签]
    V --> W[创建 SizedBox]
    W --> X[创建 Area 下拉框]
    X --> Y[创建 SizedBox]
    Y --> Z[创建 Confirm Save 按钮]

购买vip页面的代码:

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'widgets/vip_header.dart';
import 'widgets/vip_user_info.dart';
import 'widgets/member_combo.dart';
import 'widgets/member_benefits.dart';
import 'widgets/vip_purchase.dart';
class VipScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: SafeArea(
        bottom: false, // 不处理底部安全区域
        child: Column(
          children: [
            Expanded(
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    VipHeader(),
                    VipUserInfo(),
                    MemberCombo(),
                    MemberBenefits(),
                  ],
                ),
              ),
            ),
            VipPurchase(),
          ],
        ),
      ),
    );
  }
}

可以看到 首页只是用来引用组件,

vip_purchase.dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class VipPurchase extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 30.w),
      decoration: BoxDecoration(
        color: const Color(0xFF393939),
        borderRadius: BorderRadius.circular(4.r),
      ),
      child: Column(
        // mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(height: 30.h),
          Row(
            children: [
              Image.asset(
                'assets/images/vip_auto_renew.png',
                width: 32.w,
                height: 32.h,
                color: const Color(0xFFECD29F),
              ),
              SizedBox(width: 20.w),
              Text(
                'Automatic renewal',
                style: TextStyle(
                  color: const Color(0xFFECD29F),
                  fontSize: 32.sp,
                ),
              ),
            ],
          ),
          SizedBox(
            height: 133.h,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    Text(
                      'Amount: ',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 32.sp,
                      ),
                    ),
                    Text(
                      '\$89',
                      style: TextStyle(
                        color: const Color(0xFFECD29F),
                        fontSize: 32.sp,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ],
                ),
                GestureDetector(
                  onTap: () {
                    print('Buy clicked');
                  },
                  child: Container(
                    width: 340.w,
                    height: 70.h,
                    decoration: BoxDecoration(
                      color: const Color(0xFFE56389),
                      borderRadius: BorderRadius.circular(35.r),
                    ),
                    child: Center(
                      child: Text(
                        'Buy',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 36.sp,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

member_combo.dart

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: 28.sp,
                              fontWeight: FontWeight.w400,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

本章其他界面也没有复杂的部分,其他代码直接登录gitee 去看即可,已经公开的,我们接下来直接进入SDK应用创建部分

直播sdk创建

先是直播sdk,正常用户只有一次机会,14天测试期,要珍惜,如果测试完了过期的不能删除,也无法使用

核心资料是app name License URL和License Key

即时通讯im

即时通讯的关键信息,
SDKAppID:

1600071385

应用名称:

freefirend

密钥:
这里就脱敏一下。

目录
相关文章
|
6月前
|
移动开发 小程序 Android开发
基于 uni-app 开发的废品回收类多端应用功能与界面说明
本文将对一款基于 uni-app 开发的废品回收类多端应用,从多端支持范围、核心功能模块及部分界面展示进行客观说明,相关资源信息也将一并呈现。
224 0
|
6月前
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
496 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
|
7月前
|
存储 Java PHP
轻量化短视频电商直播带货APP源码全解析:核心功能与设计流程​
在电商直播热潮下,开发专属直播带货APP成为抢占市场关键。本文详解原生开发轻量化APP的核心功能与全流程设计,涵盖用户登录、商品浏览、直播互动、购物车、订单及售后功能,并介绍安卓端Java、苹果端Object-C、后台PHP的技术实现,助力打造高效优质的直播电商平台。
|
8月前
|
Java Shell Maven
【Azure Container App】构建Java应用镜像时候遇无法编译错误:ERROR [build 10/10] RUN ./mvnw.cmd dependency:go-offline -B -Dproduction package
在部署Java应用到Azure Container App时,构建镜像过程中出现错误:“./mvnw.cmd: No such file or directory”。尽管项目根目录包含mvnw和mvnw.cmd文件,但依然报错。问题出现在Dockerfile构建阶段执行`./mvnw dependency:go-offline`命令时,系统提示找不到可执行文件。经过排查,确认是mvnw文件内容异常所致。最终通过重新生成mvnw文件解决该问题,镜像成功构建。
416 1
|
8月前
|
存储 移动开发 监控
App Trace功能实战:一键拉起、快速安装与免提写邀请码的应用实践
App Trace系统通过一键拉起、快速安装和免提写邀请码三大功能,显著提升用户转化率、安装成功率和邀请注册率。结合深度技术实现与优化,助力公司用户增长,成为移动端核心基础设施。
|
10月前
|
搜索推荐 API UED
淘宝/天猫获得淘宝app商品详情原数据 API 返回值的应用
该API专注于商品信息整合与展示,提供基础信息抓取、多媒体内容整合等功能,助力实时同步商品数据,构建丰富的详情页。同时支持数据分析与市场洞察,包括销售趋势分析和竞品对比,优化库存与定价策略。此外,动态促销管理和个性化推荐系统可提升营销效果,而实时库存预警和评价数据可视化则显著增强用户体验,为用户决策提供透明依据,全面提升平台竞争力与用户满意度。
|
小程序
【04】微信支付商户申请下户到配置完整流程-微信开放平台移动APP应用通过-微信商户继续申请-微信开户函-视频声明-以及对公打款验证-申请+配置完整流程-优雅草卓伊凡
【04】微信支付商户申请下户到配置完整流程-微信开放平台移动APP应用通过-微信商户继续申请-微信开户函-视频声明-以及对公打款验证-申请+配置完整流程-优雅草卓伊凡
871 1
【04】微信支付商户申请下户到配置完整流程-微信开放平台移动APP应用通过-微信商户继续申请-微信开户函-视频声明-以及对公打款验证-申请+配置完整流程-优雅草卓伊凡
|
10月前
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
339 15
|
10月前
|
编解码 前端开发 Java
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发三
本文介绍了基于声明式UI范式的图形绘制与动画效果实现方法,涵盖绘制图形、添加动画效果及常见组件说明三部分内容。在绘制图形部分,详细讲解了如何通过Circle组件为食物成分表添加圆形标签,以及使用Path组件结合SVG命令绘制自定义图形(如应用Logo)。动画效果部分则展示了如何利用animateTo实现闪屏动画,包括渐出、放大效果,并设置页面跳转;同时介绍了页面间共享元素转场动画的实现方式。最后,文章列举了声明式开发范式中的各类组件及其功能,帮助开发者快速上手构建复杂交互页面。
368 11
|
9月前
|
JavaScript 前端开发 UED
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发四
本文介绍了Web组件开发与性能优化的相关内容。在Web组件开发部分,涵盖创建组件、设置样式与属性、添加事件和方法以及场景示例,如动态播放视频。性能提升方面,推荐使用数据懒加载、条件渲染替代显隐控制、Column/Row替代Flex、设置List组件宽高及调整cachedCount减少滑动白块等方法,以优化应用性能与用户体验。
323 56