一、配景
在开发鸿蒙应用时,我们常常需要实现一些复杂的布局效果,好比文字环绕动态文本的效果。这种效果类似于文字环绕图片,但需要环绕的文本是动态生成的,并且带有边框和样式。传统的布局组件(如 Row)无法直接实现这种效果,由于 Row 的换行逻辑是基于每个子组件的起始端,无法实现第二个文本环绕第一个文本的效果。
下面介绍如何通过 组件截图 和 ImageSpan 来实现文字环绕动态文本的效果。
二、实现思路
1. 初步实验:使用 Row 组件
最初的想法是使用 Row 组件包裹两个 Text 组件,分别表示需要环绕的文本和主文本。然而,Row 组件的布局方式是左右排列,当文本换行时,第二个 Text 组件会基于自己的起始端换行,无法实现环绕效果。
如下效果:
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 = false aboutToAppear(): 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 嵌入到主文本中,实现了类似文字环绕图片的布局效果。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |