經過了一個月高強度爆肝開發原生鴻蒙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...
路由json檔案
鴻蒙os封裝通用導航條
之前有寫過一篇專門的分享介紹,感興趣的可以去看看下面這篇文章。
https://segmentfault.com/a/1190000045431284
聊天入口檔案
// 自定義頁面
@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])
}
// 自定義底部選單欄
@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])
}
}
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實現下拉重新整理/微信九宮格圖/右鍵選單
下拉重新整理功能
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%') }
- 長按右鍵選單
.bindContextMenu(this.customCtxMenu, ResponseType.LongPress)
// 自定義長按右鍵選單
@Builder customCtxMenu() {
Menu() {
MenuItem({
content: '標為已讀'
})
MenuItem({
content: '置頂該聊天'
})
MenuItem({
content: '不顯示該聊天'
})
MenuItem({
content: '刪除'
})
}
}
下拉選單
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: () => {} } ])
- 自定義彈窗元件
引數配置
// 標題(支援字串|自定義元件)
@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