鸿蒙开发实战案例:群头像拼接案例
2025-04-12 本文已影响0人
迪士尼在逃程序员
介绍
本示例介绍使用组件截图实现组件的截图并获取pixelMap对象。该场景多用于通信类应用。
效果图预览
使用说明
- 进入群头像案例页面,点击右上角添加图标,在弹出的菜单中点击发起群聊,跳转至发起群聊页面。
- 在发起群聊页面中,点击下方用户列表前的选择框,选中多个用户,点击右下方完成按钮,添加会话数据。
- 在案例首页可以查看新增的会话数据,并可根据选择的用户自行展示群头像。
实现思路
利用组件截图能力获取群头像绘制组件图像。当组件的visibility属性不为None时,均可进行组件截图。
- 通过选择的数据,组装群头像布局组件数据。
/**
* 将选择的头像列表组装为二维数组,用于填充九宫格组件
* @param images
* @returns
*/
function divideImage2Group(personGroup: PersonData[]): GroupAvatarModel[][] {
let imageGroup: GroupAvatarModel[][] = [];
if (personGroup.length <= 4) {
// 人数少于等于4时,显示两行两列
imageGroup = divideGroupBySize(personGroup, 2);
} else if (personGroup.length <= 9) {
// 人数大于4时,显示三行三列
imageGroup = divideGroupBySize(personGroup, 3);
} else {
// 人数大于9时,仅显示前9个头像
imageGroup = divideGroupBySize(personGroup.slice(0, 9), 3);
}
return imageGroup;
}
/**
* 根据群组数量判断排列方式
* 当群成员人数大于4人,则成员头像为整体区域的1/3,按照九宫格排列
* 当群成员人数小于等于5人,则成员头像为整体区域的1/2,按照四宫格排列
* @param images
* @param rowSize
* @returns
*/
function divideGroupBySize(personData: PersonData[], rowSize: number): GroupAvatarModel[][] {
const imageCount: number = personData.length;
const imageGroup: GroupAvatarModel[][] = [];
let imageWidth: number = 0;
let imageHeight: number = 0;
let rowCount: number = 0;
let firstRowCount: number = 0;
// 设置群成员头像大小与排列方式
if (rowSize === 2) {
imageWidth = 30;
imageHeight = 30;
rowCount = Math.floor(imageCount / 2);
firstRowCount = imageCount % 2;
} else if (rowSize === 3) {
imageWidth = 20;
imageHeight = 20;
rowCount = Math.floor(imageCount / 3);
firstRowCount = imageCount % 3;
}
// 组装第一组图片数据
const firstRowGroup: GroupAvatarModel[] = [];
for (let i = 0; i < firstRowCount; i++) {
firstRowGroup.push({
src: personData[i].headImg,
width: imageWidth,
height: imageHeight
});
}
// 当取余为0时,不需要单独设置首行组件
if (firstRowGroup.length > 0) {
imageGroup.push(firstRowGroup);
}
// 根据排列方式与非首行数,组装剩余的图片数据
for (let i = 0; i < rowCount; i++) {
const fullRowImages: PersonData[] =
personData.slice(firstRowCount + i * rowSize, firstRowCount + (i + 1) * rowSize);
const fullRowGroup: GroupAvatarModel[] = [];
fullRowImages.forEach((img: PersonData) => {
fullRowGroup.push({
src: img.headImg,
width: imageWidth,
height: imageHeight
});
});
imageGroup.push(fullRowGroup);
}
return imageGroup;
}
- 通过嵌套两层ForEach组件,实现纵向与横向的线性布局。
// 绘制组件,用于绘制群组头像
Column({ space: 2 }) {
ForEach(divideImage2Group(this.selectPersonGroup), (item: GroupAvatarModel[]) => {
RowComponent(item)
})
}
// 设置组件ID,用于进行组件截图
.id('avatar_group')
.width(64)
.height(64)
.justifyContent(FlexAlign.Center)
// 设置组件隐藏
.visibility(Visibility.Hidden)
/**
* 群组头像横向列表组件
* @param imageArray
*/
@Builder
function RowComponent(imageArray: GroupAvatarModel[]) {
Row({ space: 2 }) {
ForEach(imageArray, (item: GroupAvatarModel) => {
Image(typeof item.src === 'string' ? $rawfile(item.src) : item.src)
.height(item.height)
.width(item.width)
})
}
.width(64)
.justifyContent(FlexAlign.Center)
}
- 使用Stack组件与visibility属性控制组件不显示,设置id属性,用于后续的组件截图操作。
// 使用堆叠组件,实现绘制组件在loading动画后执行
Stack() {
// 绘制组件,用于绘制群组头像
Column({ space: 2 }) {
ForEach(divideImage2Group(this.selectPersonGroup), (item: GroupAvatarModel[]) => {
RowComponent(item)
})
}
// 设置组件ID,用于进行组件截图
.id('avatar_group')
.visibility(Visibility.Hidden)
// loading弹框
Column() {
...
}
}
- 使用@ohos.arkui.componentSnapshot 接口实现组件截图,并获取群头像资源。
this.getUIContext()
.getComponentSnapshot()
.get('avatar_group', (error: Error, pixelMap: image.PixelMap) => {
...
})
高性能知识点
不涉及
工程结构&模块类型
groupavatar // har类型
|---datasource
| |---DataSource.ets // 本地数据
| |---GroupAvatarModel.ets // 数据模型
|---view
| |---components
| | |---BottomBarContent.ets // 底部Tab组件
| | |---CustomLoadingComponent.ets // loading弹框&群头像绘制组件
| | |---NavigationBarContent.ets // 顶部导航栏
| | |---PersonContent.ets // 用户列表页面
| | |---SessionContent.ets // 会话列表页面
| |---GroupAvatarAddPage.ets // 发起群聊页面
| |---GroupAvatarAddPage.ets // 首页
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习知识点,请移步前往小编:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu