【HarmonyOS NEXT】实现文字环绕动态文本效果
一、配景在开发鸿蒙应用时,我们常常需要实现一些复杂的布局效果,好比文字环绕动态文本的效果。这种效果类似于文字环绕图片,但需要环绕的文本是动态生成的,并且带有边框和样式。传统的布局组件(如 Row)无法直接实现这种效果,由于 Row 的换行逻辑是基于每个子组件的起始端,无法实现第二个文本环绕第一个文本的效果。
下面介绍如何通过 组件截图 和 ImageSpan 来实现文字环绕动态文本的效果。
二、实现思路
1. 初步实验:使用 Row 组件
最初的想法是使用 Row 组件包裹两个 Text 组件,分别表示需要环绕的文本和主文本。然而,Row 组件的布局方式是左右排列,当文本换行时,第二个 Text 组件会基于自己的起始端换行,无法实现环绕效果。
如下效果:
https://i-blog.csdnimg.cn/direct/49d20c8e27c24c7998685ea52bee196c.png
2. 解决方案:组件截图 + ImageSpan
为了实现文字环绕效果,采用了以下方案:
[*] 使用 componentSnapshot 组件对需要环绕的文本进行截图,生成图片。
[*] 将截图通过 ImageSpan 嵌入到主文本中,实现文字环绕图片的效果。
三、详细实现
3.1 组件截图:componentSnapshot
componentSnapshot 是鸿蒙 ArkUI 提供的一个 API,用于获取组件的截图。它支持截取已加载组件的内容,并将结果保存为 PixelMap 对象。
3.1.1 导入模块
起首,需要导入 componentSnapshot 模块:
import { componentSnapshot } from '@kit.ArkUI'; 3.1.2 界说需要截图的组件
我们界说一个带有边框和样式的 Text 组件,作为需要环绕的文本:
//获取需要加载组件的文本
@Builder
hotTopText() {
Text('精选')
.borderRadius(2)
.border({
width: 0.5,
color: '#0165B8',
style: BorderStyle.Solid
})
.fontSize(12)
.fontColor('#0165B8')
.backgroundColor('#DBEFFF')
.padding({
left: 2,
right: 2
})
.margin({ top: 5 })
.height(15)
.id('hotTopText') //组件标识
.visibility(this.isShowTag ? Visibility.Visible : Visibility.None)
} 3.1.3 获取组件截图
通过 componentSnapshot.get 方法获取组件的截图:
getComponentSnapshot() {
this.isShowTag = true
// 增加延迟,确保组件渲染完成
setTimeout(() => {
componentSnapshot.get('hotTopText', { scale: 2, waitUntilRenderFinished: true })
.then((pixmap: image.PixelMap) => {
this.pixmap = pixmap;
this.isShowTag = false
})
.catch(() => {
console.log('lucy== 获取标签快照失败')
});
}, 100);
} 3.2 使用 ImageSpan 实现文字环绕
将截图通过 ImageSpan 嵌入到主文本中,实现文字环绕效果:
Row() {
this.hotTopText() //只有加载了才能获取截图
Text() {
ImageSpan(this.pixmap)
.height(14)
.width('auto')
.verticalAlign(ImageSpanAlignment.CENTER)
.margin({ right: 3 })
.objectFit(ImageFit.Contain)
Span('HarmonyOS NEXT 全栈自研架构,鸿蒙原生应用,带来全新体验')
.fontSize(15)
.fontWeight(FontWeight.Medium)
}
.align(Alignment.Top)
.textAlign(TextAlign.Start)
}
.margin({
top: 12,
})
.padding(12)
.borderWidth(1)
.borderColor(Color.Red) 四、完整代码
以下是完整的实现代码:
import { image } from '@kit.ImageKit'import { componentSnapshot } from '@kit.ArkUI'@Entry@Componentstruct TextSpanPage {@State pixmap: image.PixelMap | undefined = undefined@State isShowTag: boolean = falseaboutToAppear(): void { this.getComponentSnapshot()}getComponentSnapshot() {
this.isShowTag = true
// 增加延迟,确保组件渲染完成
setTimeout(() => {
componentSnapshot.get('hotTopText', { scale: 2, waitUntilRenderFinished: true })
.then((pixmap: image.PixelMap) => {
this.pixmap = pixmap;
this.isShowTag = false
})
.catch(() => {
console.log('lucy== 获取标签快照失败')
});
}, 100);
}build() { Row() {
this.hotTopText() //只有加载了才能获取截图
Text() {
ImageSpan(this.pixmap)
.height(14)
.width('auto')
.verticalAlign(ImageSpanAlignment.CENTER)
.margin({ right: 3 })
.objectFit(ImageFit.Contain)
Span('HarmonyOS NEXT 全栈自研架构,鸿蒙原生应用,带来全新体验')
.fontSize(15)
.fontWeight(FontWeight.Medium)
}
.align(Alignment.Top)
.textAlign(TextAlign.Start)
}
.margin({
top: 12,
})
.padding(12)
.borderWidth(1)
.borderColor(Color.Red)}//获取需要加载组件的文本
@Builder
hotTopText() {
Text('精选')
.borderRadius(2)
.border({
width: 0.5,
color: '#0165B8',
style: BorderStyle.Solid
})
.fontSize(12)
.fontColor('#0165B8')
.backgroundColor('#DBEFFF')
.padding({
left: 2,
right: 2
})
.margin({ top: 5 })
.height(15)
.id('hotTopText') //组件标识
.visibility(this.isShowTag ? Visibility.Visible : Visibility.None)
}} 五、最终效果
通过以上方法,实现了文字环绕动态文本的效果。动态文本被截图为图片,并通过 ImageSpan 嵌入到主文本中,实现了类似文字环绕图片的布局效果。
https://i-blog.csdnimg.cn/direct/50f578a224284970a0db6050def451bf.png
https://i-blog.csdnimg.cn/direct/d127ea96239647669b32d3d7534e275f.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]