鸿蒙发展的真快呀,半年前还在用api9,现在直接api12了。下载新的模拟机时发现,DevEcoStudio都从3.1下载到了现在的5.0了,这算不算见证了它的成长呢,哈哈。
想尝试简单写一个聊天页面调用模型,尝试下语法方面有什么变化,然后发现很简单的聊天UI,尽然会有这么多坑,害!话不多说开干!
一、滚动聊天区域
想想一个聊天区域无非就是一个滚动列表判断一下然后弹性布局左右对齐,太简单了,使用Scroll这个可滚动的容器组件,将消息列表遍历一下,单独定义消息的左右对齐,完事!
这时出现了第一个不好控制的效果,当对话少无法占满滚动区域大小尽然是默认居中!

当子组件的布局尺寸超过父组件的尺寸时,内容才可以滚动,翻了会官网文档没找到Scroll内元素向上对齐的方法
只好动用空空的脑袋想一想了:
想到就干:设置子组件最小长度为Scroll容器长度
1
| .constraintSize({minHeight:"100%"})
|
可以!(可以是可以哈,后续一个bug,好像就这样玩出来的 TAT )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Scroll() { Column(){ ForEach(this.messages, (item: message) => { Flex({justifyContent: item.role === 'user' ? FlexAlign.End : FlexAlign.Start}) { if (item.role === 'user') { ItemComponent(item, true) } else { ItemComponent(item, false) } } }) } .constraintSize({minHeight:"100%"}) } .width("100%") .height("90%") .scrollBar(BarState.Off)
|
二、消息左右对齐与传输数据格式
1、消息如何设置左右对齐
是我的消息我就放右边,不是我的就放左边,判断判断
这里可以用if
非常好,那就简单了,来个参数告诉我这条消息是不是自己的,然后:
Flex
布局容器 里面用三目运算符设置对齐方式,可以吧
头像左右不好控制用if
控制其显示,是不是很方便
最后就是颜色,大小,样式的调整了,没啥美感就这样了,开摆

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Builder function ItemComponent(item: message, isSelf: boolean) { Flex({ justifyContent:isSelf ? FlexAlign.End : FlexAlign.Start}) { if(!isSelf) { Image($r("app.media.chatbot")) .width("50vp") } Text(item.content) .fontSize(16) .lineHeight(24) .backgroundColor(isSelf ? '#ffdddd' : '#ddffdd') .padding({ top: 8, bottom: 8, left: 10, right: 10 }) .borderRadius(10) .textAlign(TextAlign.Start) .constraintSize({maxWidth: "240vp"})
if(isSelf) { Image($r("app.media.me")) .width("50vp") } } .margin({ top: 4, bottom: 4 }) }
|
2、传输数据格式
因为要知道是谁发的消息就记录了一下角色,对比了一下QQ,想到昵称尽然没有,等待后续加工中…
写到json格式的数据,需要取返回消息的一个值,HarmonyOS next不在支持any了,语法检查有点严格哈,只好自定义类型了。
需要哪个字段定义哪个好像也行,偷懒不可取哦
因为接口调用要将全部上下文消息整体发送过去,所以定义了个messages数组,还可以forearch展示用的也是这个数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class message{ role: string; content: string; constructor(role: string, content: string) { this.role = role this.content = content } }
interface userInfo{ id: string, object: string, created: string, result: string is_truncated: boolean, need_clear_history: boolean, finish_reason: string }
@State messages: Array<message> = [ new message("user","你好"), new message("assistant", "你好,请问有什么我可以帮助你的吗?无论你有什么问题或需要帮助,我都会尽力回答和协助你。请随时告诉我你的需求。") ];
|
三、输入框和发送
这里有个bug很难受,各位大佬,求评论,救救 TAT
一个输入框,一个按钮发送,用预览器调试挺方便的,然后到了模拟机有个叫 键盘 的东东没考虑到。
这个东西尽然会把,消息给顶上去!消息少时就输入键盘一跳出来就白白了 (看不到消息了)
研究了一下微信,消息少时输入时消息是顶格的,消息多时输入消息看到的最下放时最新消息,也就滚动到了看的见最下方
尝试解决:
- 一、翻动我’’可爱’’的官方文档 找到一个叫 Scroller 的可滚动容器组件的控制器,当它按下时,获取当前消息区域滚动条的位置,当它抬起时,让它回到按下时的位置,无效
- 二、搜索其他语言解决办法:vue聊天页面在进入之后信息滑动到底部位置 然后还是翻动我’’可爱’’的官方文档,不知道该怎么搜索,没找到相应的函数
- 三、求救
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| myScroll: Scroller = new Scroller(); locat: OffsetResult = {xOffset: 0, yOffset: 0};
Row() { TextInput({ text: this.inputText, placeholder: '输入你想询问的问题' }) .height(40) .width("70%") .onChange((val) => { this.inputText = val }) .margin({right: 2}) .onClick(() => { this.locat = this.myScroll.currentOffset(); }) .onEditChange((isEditing) => { if(isEditing) { this.myScroll.scrollTo(this.locat); } }) Button('发送') .onClick(() => { this.messages.push(new message("user", this.inputText)) this.inputText = '' getTake(this.messages, this.token).then((response: AxiosResponse<userInfo>) =>{ let text = response.data.result this.messages.push(new message("assistant", text)) }) }) } .justifyContent(FlexAlign.Center) .height("10%")
|
四、AI接口调用
这个我会,我会使用axios,突然想到新版不知道能不能用,证明结果:axios已经适配鸿蒙HarmonyOS NEXT
OpenHarmony三方库中心仓 axios
1
| import axios, {AxiosResponse} from '@ohos/axios'
|
这里调用的是文兴一言模型,要调用什么ai可查看其开发文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const apiKey = "xxxxxx" const secret = "xxxxxxxxxxx"
export function get_access_token(){ return axios.post(`/oauth/2.0/token?grant_type=client_credentials&client_id=${apiKey}&client_secret=${secret}`) }
export function getTake(messages: Array<message>, token: string): Promise<AxiosResponse>{ const params = JSON.stringify({ messages: messages }) return axios.post(`/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=${token}`, params) }
|
同时HarmonyOS next 内置了很多AI服务 哦
如:textToSpeech (文本转语音) import { textToSpeech } from '@kit.CoreSpeechKit';
objectDetection(多目标识别)import { visionBase, objectDetection } from '@kit.CoreVisionKit;
等
具体查看官方文档:AI | 华为开发者联盟 (huawei.com)
五、总结
果然手搓UI界面得:一、先设计,二、懂布局
换句话说:创建UI界面时,首要步骤是进行精心的设计,其次则需要深入理解并掌握布局技巧。
HanmonyOS next入门很简单,但最好一个产品很不容易,欢迎来一起学习
最后附上效果图和源码地址
一、效果图


二、目录结构

三、源码地址
源码:https://atomgit.com/leaf-domain/chatUI
openharmony最新开发文档:https://docs.openharmony.cn/pages/v5.0/zh-cn/device-dev/quick-start/quickstart-overview.md
最新工具:https://developer.huawei.com/consumer/cn/download