项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

1. 概述

在移动应用界面设计中,图文混排卡片是一种常见且实用的UI组件,它通过将图标和文本组合在一起,以简洁明了的方式呈现信息。本教程将详细讲解如何使用HarmonyOS NEXT的Row组件创建一个精美的图文混排卡片,实现左侧图标与右侧多行文本的布局效果。

图文混排卡片广泛应用于各类应用场景,如通知提醒、功能介绍、信息展示等。通过合理的布局和样式设置,可以提升用户体验和界面美观度。

2. 图文混排卡片的设计原则

在设计图文混排卡片时,需要遵循以下设计原则:

  1. 简洁明了:卡片内容应简洁明了,避免信息过载。
  2. 视觉层次:通过大小、颜色、间距等元素建立清晰的视觉层次。
  3. 对齐一致:保持元素对齐,创造整洁有序的视觉效果。
  4. 留白适当:合理使用留白,提高内容可读性。
  5. 响应式设计:适应不同屏幕尺寸,确保良好的显示效果。

3. 案例分析:图文混排卡片

本案例展示了如何创建一个包含左侧图标和右侧多行文本的卡片组件。

3.1 完整代码

@Component
export struct IconTextCard {
    private content: string = '这是一段多行文字,演示图文混排效果。' +
        '支持自动换行,适应不同屏幕宽度。'

    build() {
        Row() {
            Image($r('app.media.05'))
                .width(24)
                .height(24)
                .margin({ right: 8 })

            Text(this.content)
                .fontSize(14)
                .maxLines(3) // 最多显示3行
        }
        .padding(16)
        .backgroundColor(Color.White)
        .borderRadius(8)
        .shadow({ radius: 4, color: '#F0F0F0' })
        .width('90%')
    }
}

3.2 代码详解

3.2.1 组件声明与属性定义

@Component
export struct IconTextCard {
    private content: string = '这是一段多行文字,演示图文混排效果。' +
        '支持自动换行,适应不同屏幕宽度。'

这部分代码声明了一个名为IconTextCard的自定义组件,并定义了一个私有属性content,用于存储卡片中显示的文本内容。

属性类型说明默认值
contentstring卡片中显示的文本内容示例文本

3.2.2 Row容器设置

Row() {
    // 子组件
}
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ radius: 4, color: '#F0F0F0' })
.width('90%')

这部分代码创建了一个Row容器,作为图文混排卡片的根容器。Row容器的属性设置如下:

属性说明
padding16设置内边距为16vp,使内容与边缘保持适当距离
backgroundColorColor.White设置背景色为白色,提供干净的视觉效果
borderRadius8设置边框圆角为8vp,使卡片四角呈现圆润效果
shadow{ radius: 4, color: '#F0F0F0' }添加阴影效果,增强卡片的立体感
width'90%'设置卡片宽度为父容器的90%,留出适当边距

这些属性设置使卡片具有现代化的设计风格,包括圆角、阴影和适当的内边距,提升了用户界面的美观度和专业感。

3.2.3 图标设置

Image($r('app.media.05'))
    .width(24)
    .height(24)
    .margin({ right: 8 })

这部分代码创建了一个Image组件,用于显示卡片左侧的图标。Image组件的属性设置如下:

属性说明
资源$r('app.media.05')使用应用资源中的图片作为图标
width24设置图标宽度为24vp
height24设置图标高度为24vp
margin{ right: 8 }设置右侧外边距为8vp,与文本保持适当距离

图标大小设置为24×24vp,这是移动界面中常用的图标尺寸,既能清晰显示图标细节,又不会占用过多空间。右侧外边距的设置确保图标与文本之间有适当的间隔,提高可读性。

3.2.4 文本设置

Text(this.content)
    .fontSize(14)
    .maxLines(3) // 最多显示3行

这部分代码创建了一个Text组件,用于显示卡片右侧的文本内容。Text组件的属性设置如下:

属性说明
内容this.content显示组件属性中定义的文本内容
fontSize14设置字体大小为14fp,适合阅读
maxLines3限制最多显示3行文本,超出部分将被截断

字体大小设置为14fp,这是移动界面中常用的正文字体大小,具有良好的可读性。maxLines属性限制文本最多显示3行,这有助于控制卡片的高度,确保界面的整洁和一致性。

4. 图文混排卡片的布局原理

图文混排卡片的布局基于Row组件的水平排列特性,将图标和文本水平排列在一起。

4.1 水平排列

Row组件默认将子组件水平排列,从左到右依次排列。在本案例中,图标位于左侧,文本位于右侧,形成了简单明了的左图右文布局。

4.2 间距控制

通过设置图标的右侧外边距(margin({ right: 8 })),控制图标与文本之间的间距,确保布局美观。

4.3 多行文本处理

通过设置Text组件的maxLines属性,控制文本的显示行数,适应不同内容长度的情况。当文本内容较长时,会自动换行显示,最多显示3行,超出部分将被截断。

5. 图文混排卡片的样式优化

为了提升图文混排卡片的视觉效果和用户体验,我们可以进行以下样式优化:

5.1 卡片容器样式

.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ radius: 4, color: '#F0F0F0' })
.width('90%')

这些样式设置使卡片具有现代化的设计风格:

  1. 内边距:设置适当的内边距,使内容与边缘保持距离,提高可读性。
  2. 背景色:使用白色背景,提供干净的视觉效果,使内容更加突出。
  3. 圆角:添加圆角效果,使卡片外观更加柔和,符合现代UI设计趋势。
  4. 阴影:添加轻微的阴影效果,增强卡片的立体感,提升视觉层次。
  5. 宽度:设置为父容器的90%,留出适当边距,避免卡片紧贴屏幕边缘。

5.2 文本样式优化

可以进一步优化文本样式,提升可读性和美观度:

Text(this.content)
    .fontSize(14)
    .fontColor('#333333')  // 深灰色文本,提高可读性
    .lineHeight(20)        // 设置行高,提高多行文本的可读性
    .maxLines(3)           // 最多显示3行
    .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出部分显示省略号

这些样式设置使文本显示更加美观:

  1. 字体颜色:使用深灰色而非纯黑色,减轻视觉疲劳,提高长时间阅读的舒适度。
  2. 行高:设置适当的行高,提高多行文本的可读性,使文本看起来更加整洁。
  3. 文本溢出处理:当文本超出最大行数时,显示省略号,提示用户还有更多内容。

5.3 图标样式优化

可以为图标添加更多样式,使其更加突出:

Image($r('app.media.05'))
    .width(24)
    .height(24)
    .margin({ right: 12 })  // 增加右侧间距
    .objectFit(ImageFit.Contain) // 确保图标完整显示
    .borderRadius(4)       // 为图标添加轻微圆角

这些样式设置使图标显示更加精美:

  1. 间距调整:增加图标与文本之间的间距,提高可读性。
  2. 图像适配:使用objectFit属性确保图标完整显示,不会被拉伸或裁剪。
  3. 圆角处理:为图标添加轻微的圆角,使其与卡片整体风格保持一致。

6. 图文混排卡片的交互优化

为了提升用户体验,可以为卡片添加交互效果:

6.1 点击效果

Row() {
    // 子组件
}
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
.shadow({ radius: 4, color: '#F0F0F0' })
.width('90%')
.onClick(() => {
    // 处理点击事件
    console.info('卡片被点击')
})
.stateStyles({
    pressed: {
        backgroundColor: '#F5F5F5',  // 按下时背景色变化
        scale: { x: 0.98, y: 0.98 }  // 按下时轻微缩小
    }
})

这些设置使卡片具有良好的点击反馈:

  1. 点击事件处理:添加onClick事件处理函数,响应用户点击。
  2. 状态样式:使用stateStyles设置按下状态的样式,当用户按下卡片时,背景色变为浅灰色,并且卡片轻微缩小,提供明确的视觉反馈。

6.2 长按效果

.gesture(
    LongPressGesture()
        .onAction(() => {
            // 处理长按事件
            console.info('卡片被长按')
        })
)

添加长按手势识别,可以为卡片提供额外的交互方式,如显示更多操作选项。

7. 图文混排卡片的扩展功能

基于本案例的基本结构,我们可以扩展更多功能:

7.1 可折叠文本

@Component
export struct ExpandableIconTextCard {
    private content: string = '这是一段较长的文字,演示可折叠文本效果。当文本内容较多时,可以通过点击展开/收起按钮查看完整内容。'
    @State isExpanded: boolean = false
    
    build() {
        Row() {
            Image($r('app.media.05'))
                .width(24)
                .height(24)
                .margin({ right: 8 })
                
            Column() {
                Text(this.content)
                    .fontSize(14)
                    .maxLines(this.isExpanded ? 999 : 2) // 展开时显示全部,收起时显示2行
                    .textOverflow({ overflow: TextOverflow.Ellipsis })
                    
                if (this.content.length > 50) { // 文本较长时显示展开/收起按钮
                    Text(this.isExpanded ? '收起' : '展开')
                        .fontSize(12)
                        .fontColor('#007DFF')
                        .margin({ top: 4 })
                        .onClick(() => {
                            this.isExpanded = !this.isExpanded
                        })
                }
            }
        }
        .padding(16)
        .backgroundColor(Color.White)
        .borderRadius(8)
        .shadow({ radius: 4, color: '#F0F0F0' })
        .width('90%')
    }
}

这个扩展功能允许用户通过点击"展开"/"收起"按钮来查看完整的文本内容,适用于文本内容较长的情况。

7.2 多图标支持

@Component
export struct MultiIconTextCard {
    private content: string
    private primaryIcon: Resource
    private secondaryIcon?: Resource // 可选的次要图标
    
    build() {
        Row() {
            // 主图标
            Image(this.primaryIcon)
                .width(24)
                .height(24)
                .margin({ right: 8 })
                
            // 文本内容
            Text(this.content)
                .fontSize(14)
                .maxLines(3)
                .flexGrow(1) // 占据剩余空间
                
            // 次要图标(如果有)
            if (this.secondaryIcon) {
                Image(this.secondaryIcon)
                    .width(20)
                    .height(20)
                    .margin({ left: 8 })
            }
        }
        .padding(16)
        .backgroundColor(Color.White)
        .borderRadius(8)
        .shadow({ radius: 4, color: '#F0F0F0' })
        .width('90%')
    }
}

这个扩展功能支持在卡片右侧添加次要图标,可以用于显示状态指示、操作按钮等。

7.3 带标题的卡片

@Component
export struct TitledIconTextCard {
    private title: string = '卡片标题'
    private content: string = '卡片内容'
    private icon: Resource
    
    build() {
        Column() {
            // 标题行
            Row() {
                Image(this.icon)
                    .width(20)
                    .height(20)
                    .margin({ right: 8 })
                    
                Text(this.title)
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
            }
            .width('100%')
            .margin({ bottom: 8 })
            
            // 内容
            Text(this.content)
                .fontSize(14)
                .opacity(0.8)
                .maxLines(3)
        }
        .padding(16)
        .backgroundColor(Color.White)
        .borderRadius(8)
        .shadow({ radius: 4, color: '#F0F0F0' })
        .width('90%')
    }
}

这个扩展功能添加了卡片标题,使卡片可以显示更丰富的信息层次。

8. 图文混排卡片组件的封装与复用

为了提高代码复用性,可以将图文混排卡片封装为一个独立的组件:

@Component
export struct IconTextCard {
    // 可自定义的属性
    content: string = '' // 文本内容
    icon: Resource      // 图标资源
    maxLines: number = 3 // 最大行数
    cardWidth: string = '90%' // 卡片宽度
    backgroundColor: Color = Color.White // 背景色
    onCardClick?: () => void // 点击回调
    
    build() {
        Row() {
            Image(this.icon)
                .width(24)
                .height(24)
                .margin({ right: 8 })
                
            Text(this.content)
                .fontSize(14)
                .maxLines(this.maxLines)
                .textOverflow({ overflow: TextOverflow.Ellipsis })
        }
        .padding(16)
        .backgroundColor(this.backgroundColor)
        .borderRadius(8)
        .shadow({ radius: 4, color: '#F0F0F0' })
        .width(this.cardWidth)
        .onClick(() => {
            if (this.onCardClick) {
                this.onCardClick()
            }
        })
    }
}

然后在应用中使用这个组件:

@Entry
@Component
struct CardDemo {
    build() {
        Column({ space: 16 }) {
            // 使用自定义卡片组件
            IconTextCard({
                content: '这是第一个卡片的内容',
                icon: $r('app.media.icon1'),
                onCardClick: () => {
                    console.info('点击了第一个卡片')
                }
            })
            
            IconTextCard({
                content: '这是第二个卡片的内容,内容较长,会自动换行显示',
                icon: $r('app.media.icon2'),
                backgroundColor: '#F0F8FF',
                maxLines: 2
            })
            
            IconTextCard({
                content: '这是第三个卡片的内容',
                icon: $r('app.media.icon3'),
                cardWidth: '95%'
            })
        }
        .width('100%')
        .height('100%')
        .backgroundColor('#F5F5F5')
        .padding({ top: 20 })
    }
}

通过这种方式,可以创建具有不同内容、图标和样式的卡片,提高代码复用性和开发效率。

9. 总结

本教程详细讲解了如何使用HarmonyOS NEXT的Row组件创建精美的图文混排卡片,实现左侧图标与右侧多行文本的布局效果。


全栈若城
1 声望2 粉丝