原生鴻蒙Next5.0 api12高仿微信app聊天|harmony arkui朋友圈|語音|紅包

xiaoyan2017發表於2024-11-19

經過了一個月高強度爆肝開發原生鴻蒙HarmonyOS Next5聊天App軟體HarmonyChat。

harmonyos-wechat自研原創純血鴻蒙Next 5.0 API12 ArkUI+ArkTs仿微信App聊天例項。包括聊天、通訊錄、我的、朋友圈等模組。

鴻蒙聊天app實現了類似微信訊息UI佈局、編輯器游標位置輸入文字+emo表情圖片和gif動圖、圖片預覽、紅包、語音/位置UI、長按語音皮膚等功能。

HarmonyOS-Chat聊天app專案已經同步到我的原創作品集。
https://gf.bilibili.com/item/detail/1107424011

專案結構框架

使用DevEco Studio 5.0.0 Release 構建版本:5.0.3.906 編輯器搭建專案模板。

想要更快進階鴻蒙開發,先把官方文件擼一遍,然後找個實戰專案學習。
圖片

華為鴻蒙os開發官網
https://developer.huawei.com/consumer/cn/
ArkUI方舟UI框架
https://developer.huawei.com/consumer/cn/doc/harmonyos-refere...

f06d237ca238efb854979b678bac2e8f_1289798-20241119101035867-2063279756.png

路由json檔案
df54138f7f1be6d6a7775b64705153d9_1289798-20241119111326298-202389965.png

鴻蒙os封裝通用導航條

image.png

之前有寫過一篇專門的分享介紹,感興趣的可以去看看下面這篇文章。
https://segmentfault.com/a/1190000045431284

聊天入口檔案

image.png

// 自定義頁面
@Builder customPage() {
  if(this.pageIndex === 0) {
    IndexPage()
  }else if(this.pageIndex === 1) {
    FriendPage()
  }else if(this.pageIndex === 2) {
    MyPage()
  }
}

build() {
  Navigation() {
    this.customPage()
  }
  .toolbarConfiguration(this.customToolBar)
  .height('100%')
  .width('100%')
  .backgroundColor($r('sys.color.background_secondary'))
  .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
}

6218fe40bb1013983d69189796a493d7_1289798-20241119110730117-75646064.png

// 自定義底部選單欄
@Builder customToolBar() {
  Row() {
    Row() {
      Badge({
        count: 8,
        style: {},
        position: BadgePosition.RightTop
      }) {
        Column({space: 2}) {
          SymbolGlyph($r('sys.symbol.ellipsis_message_fill'))
          Text('聊天').fontSize(12)
        }
      }
    }
    .layoutWeight(1)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.pageIndex = 0
    })

    Row() {
      Column({space: 2}) {
        SymbolGlyph($r('sys.symbol.person_2'))
        Text('通訊錄').fontSize(12)
      }
    }
    .layoutWeight(1)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.pageIndex = 1
    })

    Row() {
      Badge({
        value: '',
        style: { badgeSize: 8, badgeColor: '#fa2a2d' }
      }) {
        Column({space: 2}) {
          SymbolGlyph($r('sys.symbol.person_crop_circle_fill_1'))
          Text('我').fontSize(12)
        }
      }
    }
    .layoutWeight(1)
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      this.pageIndex = 2
    })
  }
  .height(56)
  .width('100%')
  .backgroundColor($r('sys.color.background_secondary'))
  .borderWidth({top: 1})
  .borderColor($r('sys.color.background_tertiary'))
}

harmonyos實現登入模板/倒數計時驗證碼

/**
 * 登入模板
 * @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()
    })
}

// 驗證碼引數
@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)
  }
}

harmonyos實現下拉重新整理/微信九宮格圖/右鍵選單

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
    .bindContextMenu(this.customCtxMenu, ResponseType.LongPress)
// 自定義長按右鍵選單
@Builder customCtxMenu() {
  Menu() {
    MenuItem({
      content: '標為已讀'
    })
    MenuItem({
      content: '置頂該聊天'
    })
    MenuItem({
      content: '不顯示該聊天'
    })
    MenuItem({
      content: '刪除'
    })
  }
}
  • 下拉選單
    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: () => {}
      }
    ])
  • 自定義彈窗元件
    image.png

image.png

c831af8821f0fd1a261f869c0bb30b2f_1289798-20241119120902286-248268836.png

引數配置

// 標題(支援字串|自定義元件)
@BuilderParam title: ResourceStr | CustomBuilder = BuilderFunction
// 內容(字串或無狀態元件內容)
@BuilderParam message: ResourceStr | CustomBuilder = BuilderFunction
// 響應式元件內容(自定義@Builder元件是@State動態內容)
@BuilderParam content: () => void = BuilderFunction
// 彈窗型別(android | ios | actionSheet)
@Prop type: string
// 是否顯示關閉圖示
@Prop closable: boolean
// 關閉圖示顏色
@Prop closeColor: ResourceColor
// 是否自定義內容
@Prop custom: boolean
// 自定義操作按鈕
@BuilderParam buttons: Array<ActionItem> | CustomBuilder = BuilderFunction

透過如下方式呼叫即可。

// 自定義退出彈窗
logoutController: CustomDialogController = new CustomDialogController({
  builder: HMPopup({
    type: 'android',
    title: '提示',
    message: '確定要退出當前登入嗎?',
    buttons: [
      {
        text: '取消',
        color: '#999'
      },
      {
        text: '退出',
        color: '#fa2a2d',
        action: () => {
          router.replaceUrl({url: 'pages/views/auth/Login'})
        }
      }
    ]
  }),
  maskColor: '#99000000',
  cornerRadius: 12,
  width: '75%'
})

綜上就是HarmonyOS Next5實戰開發聊天app的一些分享,整個專案運用到的知識點還是很多,今天就先分享到這裡,希望對大家有一些幫助!

https://segmentfault.com/a/1190000045381943
https://segmentfault.com/a/1190000045331960
https://segmentfault.com/a/1190000045245775
https://segmentfault.com/a/1190000045042968
https://segmentfault.com/a/1190000044899693

相關文章