图文混排
ArkUI 开发框架提供了 Span
和 ImageSpan
两个基础组件来实现图文混排的场景,本节笔者简单讲述一下它们的用法。
Span 组件
Span
组件用来显示一段文本,它只能作为 Text 组件的子组件使用,目前只支持文本的通用属性 (opens new window),比如设置文本的颜色、大小、样式、粗细、字体、行高和装饰线等。
Span 定义介绍
interface SpanInterface {
(value: string | Resource): SpanAttribute;
}
Span
的构造方法接收一个 string
或者 Resource
类型的参数用来显示一个段文本,简单样例如下所示:
@Component @Entry struct SpanTest {
build() {
Column({space: 10}) {
Text("Hello, OpenHarmony") // 使用Text来显示文本
Text() {
Span("Hello, OpenHarmony") // 使用Span来显示文本
}
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
Span 属性介绍
declare class SpanAttribute extends CommonMethod<SpanAttribute> {
fontColor(value: ResourceColor): SpanAttribute;
fontSize(value: number | string | Resource): SpanAttribute;
fontStyle(value: FontStyle): SpanAttribute;
fontWeight(value: number | FontWeight | string): SpanAttribute;
fontFamily(value: string | Resource): SpanAttribute;
decoration(value: {
type: TextDecorationType;
color?: ResourceColor;
}): SpanAttribute;
letterSpacing(value: number | string): SpanAttribute;
textCase(value: TextCase): SpanAttribute;
}
Span
支持的属性是 Text
组件支持属性的子集,它的显示效果和 Text
是一样的,笔者不在逐一介绍了,简单样例如下所示:
@Component @Entry struct SpanTest {
build() {
Column({space: 10}) {
Text("Hello, OpenHarmony") // 使用Text做参照物
Text() {
Span("Hello,") // 设置字体颜色、大小
.fontColor(Color.Orange)
.fontSize(20)
Span("OpenHarmony") // 设置字体颜色、大小
.fontColor(Color.Orange)
.fontSize(30)
Span("Hello") // 设置字体颜色、大小、样式、字符间距、样式、粗细
.fontColor(Color.Red)
.fontSize(20)
.fontWeight(FontWeight.Bolder)
.fontStyle(FontStyle.Italic)
.letterSpacing(3)
Span("《ArkUI实战》") // 设置字体大小、装饰线以及字母大写显示
.decoration({
type: TextDecorationType.Underline,
color: Color.Red
})
.fontSize(20)
.textCase(TextCase.UpperCase)
}
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
由上述示例可知:Text 组件可以包含多个 Span
组件按照行排列的形式进行展示,超过一行默认进行换行显示。
Span 属性继承
Span 组件允许从父组件 Text 继承属性,当 Span 未设置属性而父组件 Text 设置了相关属性时,则 Span 默认继承 Text 组件设置的属性,目前支持继承的属性包括:fontColor、fontSize、fontStyle、fontWeight、decoration、letterSpacing、textCase、fontfamily。
简单样例如下所示:
@Component @Entry struct SpanTest {
build() {
Column({space: 10}) {
Text() {
Span("Hello, OpenHarmony") // 默认参照物
}
Text() {
Span("Hello, OpenHarmony") // 继承 Text 属性
}
.fontColor(Color.Red)
.fontSize(20)
Text() {
Span("Hello, OpenHarmony") // 继承 Text 属性
Span("Hello, OpenHarmony") // 覆盖 Text 属性
.fontColor(Color.Red)
.fontSize(24)
}
.fontColor(Color.Blue)
.fontSize(20)
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
由运行效果可知,当 Span 未设置相关属性而父组件 Text 设置了相关属性时,则 Span 继承父组件的熟悉,若 Span 设置了相关属性则以自身属性为准。
Span 事件介绍
Span
目前只支持点击事件:
export declare class CommonMethod<T> {
onClick(event: (event?: ClickEvent) => void): T;
}
简单例如如下所示:
import Prompt from '@system.prompt'
@Component @Entry struct SpanTest {
build() {
Column({space: 10}) {
Text("Hello, OpenHarmony")
Text() {
Span("Hello,")
.fontColor(Color.Orange)
.fontSize(20)
.onClick((event) => {
Prompt.showToast({
message: "Hello"
})
})
Span("OpenHarmony")
.fontColor(Color.Orange)
.fontSize(30)
.onClick((event) => {
Prompt.showToast({
message: "OpenHarmony"
})
})
Span("Hello")
.fontColor(Color.Red)
.fontSize(20)
.fontWeight(FontWeight.Bolder)
.fontStyle(FontStyle.Italic)
.letterSpacing(3)
.onClick((event) => {
Prompt.showToast({
message: "Hello"
})
})
Span("《ArkUI实战》")
.decoration({
type: TextDecorationType.Underline,
color: Color.Red
})
.fontSize(20)
.textCase(TextCase.UpperCase)
.onClick((event) => {
Prompt.showToast({
message: "《ArkUI实战》"
})
})
}
}
.padding(10)
.width("100%")
.height("100%")
}
}
ImageSpan
ImageSpan
组件用来在 Text
文本组件中显示一张图片,它只能作为 Text
组件的子组件使用,目前支持文本的通用属性只有尺寸、背景以及边框
ImageSpan 定义介绍
interface ImageSpanInterface {
(value: ResourceStr | PixelMap): ImageSpanAttribute;
}
ImageSpan 的构造方法接收一个 ResourceStr 或者 PixelMap 类型的参数用来显示一张图片。简单样例如下所示:
@Component @Entry struct test {
build() {
Column({space: 10}) {
Text() {
ImageSpan($r("app.media.test"))
.width("100%")
.height(120)
ImageSpan("https://face.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/2018new_xin_org.png")
.width(30)
.height(30)
ImageSpan("https://face.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/2018new_xin_org.png")
.width(30)
.height(30)
ImageSpan("https://face.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/2018new_xin_org.png")
.width(30)
.height(30)
}
.fontSize(20)
.fontColor(Color.Black)
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
当 ResourceStr 是一个网络地址时,需要在配置文件 module.json5 中添加网络权限:
{
"module": {
"name": "entry",
"requestPermissions": [
{
"name": "ohos.permission.INTERNET" // 配置网络权限
}
],
}
}
ImageSpan 属性介绍
declare class ImageSpanAttribute extends CommonMethod<ImageSpanAttribute> {
verticalAlign(value: ImageSpanAlignment): ImageSpanAttribute;
objectFit(value: ImageFit): ImageSpanAttribute;
}
objectFit: 设置图片的缩放类型,和 Image 属性一致,笔者不再多做介绍了。
verticalAlign: 在 Text 内部既有 Span 又有 ImageSpan 的场景下,ImageSpan 在竖直方向上的对其方式,目前支持以下几种:
- TOP: 图片上边沿与文本上边沿对齐。
- CENTER: 图片中间与文本中间对齐。
- BOTTOM(默认值): 图片下边沿与文本下边沿对齐。
- BASELINE: 图片下边沿与文本 BaseLine 对齐。
简单样例如下所示:
@Component @Entry struct test {
build() {
Column({space: 10}) {
Text() {
ImageSpan($r("app.media.test"))
.width(50)
.height(50)
Span("Hello, OpenHarmony")
}
Text() {
ImageSpan($r("app.media.test"))
.width(50)
.height(50)
.verticalAlign(ImageSpanAlignment.TOP)
Span("Hello, OpenHarmony")
}
Text() {
ImageSpan($r("app.media.test"))
.width(50)
.height(50)
.verticalAlign(ImageSpanAlignment.CENTER)
Span("Hello, OpenHarmony")
}
Text() {
ImageSpan($r("app.media.test"))
.width(50)
.height(50)
.verticalAlign(ImageSpanAlignment.BOTTOM)
Span("Hello, OpenHarmony")
}
Text() {
ImageSpan($r("app.media.test"))
.width(50)
.height(50)
.verticalAlign(ImageSpanAlignment.BASELINE)
Span("Hello, OpenHarmony")
}
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
ImageSpan 事件介绍
ImageSpan
目前也是只支持点击事件,它和 Span
的用法一致,笔者就不在单独介绍它的用法了
图文混排
图文混排的场景也是很常见的,比如浏览新闻类 APP 的时候经常会有图文混排的场景,在 OpenHarmony 上实现图文混排最简单的方式就是利用 Text 包含 Span 和 ImageSpan 实现,简单样例如下所示:
import Prompt from '@system.prompt'
@Component @Entry struct test {
build() {
Column({space: 10}) {
Text() {
ImageSpan($r("app.media.app_icon"))
.size({width: 25, height: 25})
.verticalAlign(ImageSpanAlignment.CENTER)
.onClick((event) => {
Prompt.showToast({
message: "Hello,《ArkUI实战》"
})
})
Span(" 新的一年已经开启,带上一本 #夜读日历# ")
.onClick((event) => {
Prompt.showToast({
message: "新的一年已经开启,带上一本 #夜读日历# ,继续乘风破浪、跨越山海吧!"
})
})
ImageSpan($r("app.media.love"))
.size({width: 25, height: 25})
.verticalAlign(ImageSpanAlignment.CENTER)
.onClick((event) => {
Prompt.showToast({
message: "感谢关注"
})
})
Span(" 继续乘风破浪、跨越山海吧!")
.onClick((event) => {
Prompt.showToast({
message: "新的一年已经开启,带上一本 #夜读日历# ,继续乘风破浪、跨越山海吧!"
})
})
ImageSpan("https://face.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/2018new_xin_org.png")
.size({width: 25, height: 25})
.verticalAlign(ImageSpanAlignment.CENTER)
.onClick((event) => {
Prompt.showToast({
message: "感谢关注"
})
})
}
.fontSize(20)
.fontColor(Color.Black)
}
.padding(10)
.width("100%")
.height("100%")
}
}
样例运行结果如下图所示:
小结
本节笔者简单介绍了使用 Span 和 ImageSpan 实现图文混排功能,目前笔者认为美中不足的是 Text 内部不支持使用 ForEach 循环创建多个 Span 的场景……