HarmonyOS Next 聊天会话详情页开发实践(一)

97 阅读1分钟

HarmonyOS Next 聊天会话详情页开发实践

概述

在 HarmonyOS Next 应用开发中,聊天会话详情页是社交或电商类应用中不可或缺的部分。下面将介绍如何构建一个具备消息展示、发送、图片预览、语音交互等功能的聊天会话详情页。

核心代码功能及对应代码段

1. 页面初始化与数据准备

在页面即将显示时,根据当前断点和导航参数获取当前会话的用户名,并加载对应的消息数据。同时,监听软键盘高度变化事件。

aboutToAppear(): void {
  if (this.currentBreakpoint === BreakpointConstants.BREAKPOINT_SM) {
    this.currentConversationUserName = String(this.pageInfo.getParamByIndex(0))
  } else {
    this.currentConversationUserName = String(this.cvsPathInfo.getParamByIndex(0))
  }
  this.messageInfo = this.currentConversationUserName === '华为官方旗舰店' ? MessageData1 : MessageData2

  window.getLastWindow(getContext(this)).then((data => {
    data.on('keyboardHeightChange', (data) => {
      this.keyBoardHeight = px2vp(data)
      if (this.keyBoardHeight > 0) {
        this.isAddDlgOpen = false
      }
    })
  }))
}
2. 页面布局与组件构建

使用 NavDestinationStack 进行页面布局,包含顶部搜索栏、消息列表、底部输入框和发送图片按钮等组件。

build() {
  NavDestination() {
    Stack() {
      Flex({ direction: FlexDirection.Column }) {
        ConversationDetailTopSearch({ currentConversationUserName: $currentConversationUserName, })
          .height(new BreakPointType({
            sm: '11%',
            md: '11%',
            lg: '10%'
          }).getValue(this.currentBreakpoint))
          .expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM])
        Scroll() {
          Column() {
            ForEach(this.messageInfo, (item: MessageDataInterface) => {
              ConversationDetailItem({
                receivedName: item.name,
                isReceived: item.isReceive,
                content: item.msg,
                type: item.type,
                onPreviewImg: this.onPreviewImg.bind(this)
              })
            })
          }
        }.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM]) 
        Blank()
        ConversationDetailBottom({onSend: this.onSend.bind(this), onOpenAddDlg: this.onOpenAddDlg.bind(this)})

        Column() {
          Divider()
          Row() {
            Image($r('app.media.ic_send_image'))
              .height(38)
              .width(38)
          }
          .onClick(() => {
            AlbumService.selectPicture((result: photoAccessHelper.PhotoSelectResult) => {
              this.onSend(result.photoUris[0], 1)
              this.isAddDlgOpen = false
              this.imageList.push(result.photoUris[0])
            })
          })
          Text('照片')
            .fontSize($r('app.float.font_size_twelve'))
            .margin({top: 5, left: 32})
            .fontColor($r('app.color.font_color_black_two'))
        }
        .alignItems(HorizontalAlign.Start)
        .height(100)
        .width('100%')
        .visibility(this.isAddDlgOpen ? Visibility.Visible : Visibility.None)
      }
      .height(StyleConstants.FULL_HEIGHT)
      .width(StyleConstants.FULL_WIDTH)
      .backgroundColor($r('app.color.background_color_grey'))
      .padding({
        bottom: deviceInfo.deviceType !== StyleConstants.DEVICE_2IN1 ?
        $r('app.float.tab_content_pb') : $r('app.float.zero'), top: AppStorage.get<string>('topAvoid') || 0
      })

      if (this.isClickImg) {
        ImageViewerComponent({
          imageList: this.imageList,
          active: this.selectIdx,
          closePreviewFn: () => {
            this.isClickImg = false
          }
        })
      }

      if (this.flagUpOpacity === 1) {
        Column() {
          // 语音交互相关组件
        }
      }
    }
  }
  .hideTitleBar(true)
}