harmony-chatroom 自研纯血鸿蒙OS Next 5.0聊天APP实战案例

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
简介: HarmonyOS-Chat是一个基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序。这个项目使用了ArkUI和ArkTS技术栈,实现了类似微信的消息UI布局、输入框光标处插入文字、emoji表情图片/GIF动图、图片预览、红包、语音/位置UI、长按语音面板等功能。

历经一个多月潜心研发,重磅原创新作原生鸿蒙harmonyos-chat聊天室项目完成了

未标题-a.png

HarmonyOS-Chat基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序,类似微信的UI界面和功能,提供了包括聊天、通讯录、我、朋友圈等模块。


p1.gif

p2.gif


ArkUI和ArkTS

ArkUI是华为鸿蒙操作系统提供的UI框架,它允许开发者创建丰富的用户界面。ArkTS则是鸿蒙操作系统的一种脚本语言,类似于JavaScript,用于编写ArkUI的应用程序逻辑。


未标题-3.png

p3.gif

arkui实现了下拉刷新、长按菜单,朋友圈等功能。

p3-2.gif

项目结构目录

HarmonyOS-Chat项目的框架结构是基于DevEco Studio 5.0.3.906编码工具构建的。

360截图20241118123651702.png


页面json文件。

df54138f7f1be6d6a7775b64705153d9_1289798-20241119111326298-202389965.png


harmonyos自定义导航条组件

image.png


ffc096406a1fdfa2b1743de6d0217661_1289798-20241119103438252-506834007.png


059e369873a0e442eca9b5de11b3c0b5_1289798-20241031124859083-39238132.png

支持如下参数配置:

@Component
export struct HMNavBar {
  // 是否隐藏左侧的返回键
  @Prop hideBackButton: boolean
  // 标题(支持字符串|自定义组件)
  @BuilderParam title: ResourceStr | CustomBuilder = BuilderFunction
  // 副标题
  @BuilderParam subtitle: ResourceStr | CustomBuilder = BuilderFunction
  // 返回键图标
  @Prop backButtonIcon: Resource | undefined = $r('sys.symbol.chevron_left')
  // 返回键标题
  @Prop backButtonTitle: ResourceStr
  // 背景色
  @Prop bgColor: ResourceColor = $r('sys.color.background_primary')
  // 渐变背景色
  @Prop bgLinearGradient: LinearGradient
  // 图片背景
  @Prop bgImage: ResourceStr | PixelMap
  // 标题颜色
  @Prop fontColor: ResourceColor
  // 标题是否居中
  @Prop centerTitle: boolean
  // 右侧按钮区域
  @BuilderParam actions: Array<ActionMenuItem> | CustomBuilder = BuilderFunction
  // 导航条高度
  @Prop navbarHeight: number = 56

  // ...
}

调用方式:

HMNavBar({
  backButtonIcon: $r('sys.symbol.arrow_left'),
  title: '鸿蒙自定义导航栏',
  subtitle: 'HarmonyOS Next 5.0自定义导航栏',
})
// 自定义渐变背景、背景图片、右侧操作区
HMNavBar({
  hideBackButton: true,
  title: 'HarmonyOS',
  subtitle: 'harmonyos next 5.0 api 12',
  bgLinearGradient: {
    angle: 135,
    colors: [['#42d392 ',0.2], ['#647eff',1]]
  },
  // bgImage: 'pages/assets/nav_bg.png',
  // bgImage: 'https://developer.huawei.com/allianceCmsResource/resource/HUAWEI_Developer_VUE/images/1025-pc-banner.jpeg',
  fontColor: '#fff',
  actions: [
    {
      icon: 'https://developer.huawei.com/allianceCmsResource/resource/HUAWEI_Developer_VUE/images/yuanfuwuicon.png',
      action: () => promptAction.showToast({ message: "show toast index 1" })
    },
    {
      icon: 'https://developer.huawei.com/allianceCmsResource/resource/HUAWEI_Developer_VUE/images/0620logo4.png',
      action: () => promptAction.showToast({ message: "show toast index 2" })
    },
    {
      icon: $r('sys.symbol.person_crop_circle_fill_1'),
      action: () => promptAction.showToast({ message: "show toast index 3" })
    }
  ],
  navbarHeight: 70
})

鸿蒙arkui实现登录/倒计时验证

p0.gif

/**
 * 登录模板
 * @author andy
 */

import { router, promptAction } from '@kit.ArkUI'

@Entry
@Component
struct Login {
  @State name: string = ''
  @State pwd: string = ''

  // 提交
  handleSubmit() {
    if(this.name === '' || this.pwd === '') {
      promptAction.showToast({ message: '账号或密码不能为空' })
    }else {
      // 登录接口逻辑...
      
      promptAction.showToast({ message: '登录成功' })
      setTimeout(() => {
        router.replaceUrl({ url: 'pages/Index' })
      }, 2000)
    }
  }

  build() {
    Column() {
      Column({space: 10}) {
        Image('pages/assets/images/logo.png').height(50).width(50)
        Text('HarmonyOS-Chat').fontSize(18).fontColor('#0a59f7')
      }
      .margin({top: 50})
      Column({space: 15}) {
        TextInput({placeholder: '请输入账号'})
          .onChange((value) => {
            this.name = value
          })
        TextInput({placeholder: '请输入密码'}).type(InputType.Password)
          .onChange((value) => {
            this.pwd = value
          })
        Button('登录').height(45).width('100%')
          .linearGradient({ angle: 135, colors: [['#0a59f7', 0.1], ['#07c160', 1]] })
          .onClick(() => {
            this.handleSubmit()
          })
      }
      .margin({top: 30})
      .width('80%')
      Row({space: 15}) {
        Text('忘记密码').fontSize(14).opacity(0.5)
        Text('注册账号').fontSize(14).opacity(0.5)
          .onClick(() => {
            router.pushUrl({url: 'pages/views/auth/Register'})
          })
      }
      .margin({top: 20})
    }
    .height('100%')
    .width('100%')
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  }
}

827ca3f17870dd64d47385a5b880e2a7_1289798-20241119113748951-657529179.png

Stack({alignContent: Alignment.End}) {
  TextInput({placeholder: '验证码'})
    .onChange((value) => {
      this.code = value
    })
  Button(`${this.codeText}`).enabled(!this.disabled).controlSize(ControlSize.SMALL).margin({right: 5})
    .onClick(() => {
      this.handleVCode()
    })
}

arkui实现60s倒计时

// 验证码参数
@State codeText: string = '获取验证码'
@State disabled: boolean = false
@State time: number = 60

// 获取验证码
handleVCode() {
  if(this.tel === '') {
    promptAction.showToast({ message: '请输入手机号' })
  }else if(!checkMobile(this.tel)) {
    promptAction.showToast({ message: '手机号格式错误' })
  }else {
    const timer = setInterval(() => {
      if(this.time > 0) {
        this.disabled = true
        this.codeText = `获取验证码(${this.time--})`
      }else {
        clearInterval(timer)
        this.codeText = '获取验证码'
        this.time = 5
        this.disabled = false
      }
    }, 1000)
  }
}

鸿蒙arkui实现下拉刷新/长按菜单

00cf7d864fd4985c00ce2972a2daee85_1289798-20241119115109602-1001433050.png

Refresh({
  refreshing: $$this.isRefreshing,
  builder: this.customRefreshTips
}) {
  List() {
    ForEach(this.queryData, (item: RecordArray) => {
      ListItem() {
        // ...
      }
      .stateStyles({pressed: this.pressedStyles, normal: this.normalStyles})
      .bindContextMenu(this.customCtxMenu, ResponseType.LongPress)
      .onClick(() => {
        // ...
      })
    }, (item: RecordArray) => item.cid.toString())
  }
  .height('100%')
  .width('100%')
  .backgroundColor('#fff')
  .divider({ strokeWidth: 1, color: '#f5f5f5', startMargin: 70, endMargin: 0 })
  .scrollBar(BarState.Off)
}
.pullToRefresh(true)
.refreshOffset(64)
// 当前刷新状态变更时触发回调
.onStateChange((refreshStatus: RefreshStatus) => {
  console.info('Refresh onStatueChange state is ' + refreshStatus)
  this.refreshStatus = refreshStatus
})
// 进入刷新状态时触发回调
.onRefreshing(() => {
  console.log('onRefreshing...')
  setTimeout(() => {
    this.isRefreshing = false
  }, 2000)
})

自定义下拉提示。

@State isRefreshing: boolean = false
@State refreshStatus: number = 1

// 自定义刷新tips
@Builder customRefreshTips() {
  Stack() {
    Row() {
      if(this.refreshStatus == 1) {
        SymbolGlyph($r('sys.symbol.arrow_down')).fontSize(24)
      }else if(this.refreshStatus == 2) {
        SymbolGlyph($r('sys.symbol.arrow_up')).fontSize(24)
      }else if(this.refreshStatus == 3) {
        LoadingProgress().height(24)
      }else if(this.refreshStatus == 4) {
        SymbolGlyph($r('sys.symbol.checkmark')).fontSize(24)
      }
      Text(`${
        this.refreshStatus == 1 ? '下拉刷新' :
          this.refreshStatus == 2 ? '释放更新' :
            this.refreshStatus == 3 ? '加载中...' :
              this.refreshStatus == 4 ? '完成' : ''
      }`).fontSize(16).margin({left:10})
    }
    .alignItems(VerticalAlign.Center)
  }
  .align(Alignment.Center)
  .clip(true)
  .constraintSize({minHeight:32})
  .width('100%')
}

53ed82dfd0d8bc4bdfb0d5f84848ac41_1289798-20241119115230213-1785508169.png

40bf4bafa8a5de2cbd5880f81356e67e_1289798-20241119115302037-837203237.png

Image($r('app.media.plus')).height(24).width(24)
  .bindMenu([
    {
      icon: $r('app.media.message_on_message'),
      value:'发起群聊',
      action: () => {}
    },
    {
      icon: $r('app.media.person_badge_plus'),
      value:'添加朋友',
      action: () => router.pushUrl({url: 'pages/views/friends/AddFriend'})
    },
    {
      icon: $r('app.media.line_viewfinder'),
      value:'扫一扫',
      action: () => {}
    },
    {
      icon: $r('app.media.touched'),
      value:'收付款',
      action: () => {}
    }
  ])

整个项目所涉及知识点非常多,希望以上分享对大家有些帮助~


目录
打赏
0
1
2
0
63
分享
相关文章
一文彻底拿下HarmonyOS NEXT开发实战调试技巧
这是一篇关于HarmonyOS NEXT开发调试技巧的文章,作者是一名经验丰富的程序员Feri。内容涵盖三种调试方法:预览+日志方式(适合简单调试,需注意数据类型转换)、断点调试(详细介绍了设置步骤与功能键使用)以及hilog实战使用(日志打印限制为4096字节,推荐封装维护)。通过这些技巧,帮助开发者更高效地解决问题,提升编程能力。
56 14
一文彻底拿下HarmonyOS NEXT开发实战调试技巧
一文彻底搞清楚HarmonyOS NEXT的元服务
简介:本文详细介绍Harmony OS中的“元服务”,一种轻量级应用程序形态,支持免安装、秒开直达、多设备运行等特性,大幅提升服务获取效率。文中对比了元服务与传统App应用的区别,阐述其六大特征:秒开直达、服务相伴、用完即走、一体两面、原生智能、高效开发。同时,文章还提供了元服务的开发流程,包括开发前准备、开发中具体步骤、打包、测试及上架发布,帮助开发者快速掌握元服务的开发与应用。
63 13
一文彻底搞清楚HarmonyOS NEXT的元服务
HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
本书深入解析HarmonyOS应用框架开发,聚焦Ability Kit与Accessibility Kit两大核心组件。Ability Kit通过FA/PA双引擎架构实现跨设备协同,支持分布式能力开发;Accessibility Kit提供无障碍服务构建方案,优化用户体验。内容涵盖设计理念、实践案例、调试优化及未来演进方向,助力开发者打造高效、包容的分布式应用,体现HarmonyOS生态价值。
53 27
HarmonyOS Next~鸿蒙AI功能开发:Core Speech Kit与Core Vision Kit的技术解析与实践
本文深入解析鸿蒙操作系统(HarmonyOS)中的Core Speech Kit与Core Vision Kit,探讨其在AI功能开发中的核心能力与实践方法。Core Speech Kit聚焦语音交互,提供语音识别、合成等功能,支持多场景应用;Core Vision Kit专注视觉处理,涵盖人脸检测、OCR等技术。文章还分析了两者的协同应用及生态发展趋势,展望未来AI技术与鸿蒙系统结合带来的智能交互新阶段。
51 31
一文彻底搞清楚HarmonyOS NEXT中的this
程序员Feri是一位拥有12年+经验的开发者,擅长Java、嵌入式、鸿蒙、人工智能等领域。本文深入探讨了ArkTS中this关键字的重要性及其核心规则。通过分析组件方法、异步回调、@Builder上下文隔离和装饰器方法中的this指向,揭示其运行机制与常见陷阱。同时提供了高阶技巧如内存管理、函数式组件优化及性能对比,并总结调试指南与最佳实践,助你构建高性能HarmonyOS NEXT应用。
52 8
HarmonyOS Next~HarmonyOS应用开发工具:DevEco Testing
HarmonyOS应用开发工具DevEco Testing,作为保障应用质量的关键利器,支持多维度测试(单元、UI、性能等)与智能化优化。其分布式测试框架、性能基线管理和智能用例推荐等功能,覆盖应用全生命周期。通过自动化测试策略、持续集成和性能调优,助力开发者高效构建高质量HarmonyOS应用,推动生态发展。
23 2
HarmonyOS Next~HarmonyOS应用开发工具之AppGallery Connect
AppGallery Connect(AGC)是华为为HarmonyOS开发者提供的全生命周期服务平台,支持开发、测试、上架到运营全流程。其核心功能包括应用分发、云数据库、认证服务和云函数等,助力开发者提升效率、缩短开发周期。AGC采用分层架构设计,集成40+云端服务能力,覆盖170+国家/地区,支持全球化业务拓展。通过事件跟踪、异常监控等工具,帮助开发者优化性能与用户体验。未来,AGC将引入低代码开发、增强现实等新能力,助力构建高质量HarmonyOS应用。
25 4
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
120 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
188 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
5天前
|
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡
46 15
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡

云原生

+关注
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等