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

效果演示

1. 引言

在上一部分中,我们介绍了垂直列表的基础结构、数据模型设计以及外层Column的实现。本教程将继续深入探讨列表项的内部结构,包括Row布局的实现、图片与文本的样式设置以及嵌套标签的实现方法,帮助开发者掌握更复杂的布局技巧,创建视觉层次分明、信息丰富的产品列表界面。

2. 列表项的Row布局实现

2.1 列表项的基本结构

Row({ space: 16 }) // 每个列表项内部用 Row 水平排列
   {
    // 左侧图片
    Image(item.image)
        .width(80)
        .height(80)
        .objectFit(ImageFit.Cover)
        .borderRadius(4)

    // 右侧内容区域(垂直排列)
    Column({ space: 8 }) {
        // 文本和标签内容
    }
} .width('100%')
.height(120)
.padding(12)
.backgroundColor(0xFFFFFF)
.borderRadius(8)
.shadow({ radius: 2, color: 0x05000000 })

每个列表项使用Row组件实现水平布局,将产品图片和详细信息分别放置在左右两侧。

2.2 Row组件属性详解

属性/参数作用
space16设置子组件之间的水平间距为16vp
width'100%'设置Row宽度占父容器的100%
height120设置Row高度为固定的120vp
padding12设置内边距为12vp,使内容与边框保持适当距离
backgroundColor0xFFFFFF设置背景色为白色
borderRadius8设置边框圆角为8vp,使列表项更美观
shadow对象添加阴影效果,提升列表项的立体感

2.3 阴影效果的实现

.shadow({ radius: 2, color: 0x05000000 })

阴影效果是卡片式设计中常用的视觉元素,可以增强界面的层次感和立体感。

参数作用
radius2设置阴影的模糊半径为2vp,值越大阴影越模糊
color0x05000000设置阴影颜色为黑色(000000)且透明度为5%(05)

在设计阴影时,应遵循以下原则:

  • 保持适度的模糊半径,避免过于锐利或过于模糊
  • 使用低透明度的颜色,避免阴影过于明显
  • 与卡片的圆角配合,创造自然的立体效果

3. 图片组件的实现

3.1 图片组件的基本结构

Image(item.image)
    .width(80)
    .height(80)
    .objectFit(ImageFit.Cover)
    .borderRadius(4)

3.2 图片组件属性详解

属性作用
构造参数item.image设置图片源,来自Product对象的image属性
width80设置图片宽度为80vp
height80设置图片高度为80vp
objectFitImageFit.Cover设置图片填充模式为覆盖,确保图片填满容器且不变形
borderRadius4设置边框圆角为4vp,使图片边角更圆润

3.3 objectFit属性的重要性

objectFit属性控制图片如何适应其容器的尺寸,在列表项中尤为重要:

ImageFit值效果描述适用场景
Cover保持宽高比缩放图片,使图片完全覆盖容器,可能裁剪部分内容产品列表、缩略图等需要统一尺寸的场景
Contain保持宽高比缩放图片,使图片完全显示在容器内,可能有空白区域需要显示完整图片内容的场景
Fill拉伸图片填满容器,可能导致图片变形背景图等不强调原始比例的场景
None保持图片原始大小,不进行缩放需要显示原始图片的场景
ScaleDown保持宽高比,在None和Contain之间选择较小的一个需要在保持原始大小和完全显示之间平衡的场景

在产品列表中,通常使用ImageFit.Cover可以确保所有产品图片具有统一的视觉效果,无论原始图片的宽高比如何。

4. 右侧内容区域的Column布局

4.1 右侧Column的基本结构

Column({ space: 8 }) {
    Text(item.title)
        .fontSize(16)
        .fontWeight(500)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
        .maxLines(1)

    Text(item.price)
        .fontSize(14)
        .fontColor(0xFF4D4F53)

    // 水平排列的标签(嵌套 Row)
    Row({ space: 4 }) {
        // 标签内容
    }
}

右侧内容区域使用Column组件垂直排列产品标题、价格和标签。

4.2 右侧Column属性详解

属性/参数作用
space8设置子组件之间的垂直间距为8vp

4.3 文本组件的实现

4.3.1 标题文本

Text(item.title)
    .fontSize(16)
    .fontWeight(500)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .maxLines(1)
属性作用
构造参数item.title设置文本内容,来自Product对象的title属性
fontSize16设置字体大小为16vp
fontWeight500设置字体粗细为中等偏粗
textOverflow{ overflow: TextOverflow.Ellipsis }设置文本溢出时显示省略号
maxLines1限制最多显示1行文本,超出部分截断

4.3.2 价格文本

Text(item.price)
    .fontSize(14)
    .fontColor(0xFF4D4F53)
属性作用
构造参数item.price设置文本内容,来自Product对象的price属性
fontSize14设置字体大小为14vp,小于标题
fontColor0xFF4D4F53设置字体颜色为深灰色

5. 嵌套标签的Row布局

5.1 标签Row的基本结构

Row({ space: 4 }) {
    Text('新品')
        .fontSize(12)
        .padding({ top: 2, bottom: 2, left: 8, right: 8 })
        .backgroundColor(0xFFF0F0)
        .borderRadius(10)

    Text('热卖')
        .fontSize(12)
        .padding({ top: 2, bottom: 2, left: 8, right: 8 })
        .backgroundColor(0xFFE5F5FF)
        .borderRadius(10)
}

标签区域使用Row组件水平排列多个标签,每个标签使用Text组件实现。

5.2 标签Row属性详解

属性/参数作用
space4设置子组件之间的水平间距为4vp

5.3 标签Text组件的实现

Text('新品')
    .fontSize(12)
    .padding({ top: 2, bottom: 2, left: 8, right: 8 })
    .backgroundColor(0xFFF0F0)
    .borderRadius(10)
属性作用
构造参数'新品'设置标签文本内容
fontSize12设置字体大小为12vp,小于价格文本
padding{ top: 2, bottom: 2, left: 8, right: 8 }设置内边距,使标签文本有适当的留白
backgroundColor0xFFF0F0设置背景色为浅红色(新品标签)
borderRadius10设置边框圆角为10vp,使标签呈胶囊形状

5.4 标签颜色的视觉区分

在本案例中,我们使用不同的背景色来区分不同类型的标签:

标签类型背景色颜色描述视觉效果
新品0xFFF0F0浅红色突出新上市的产品
热卖0xFFE5F5FF浅蓝色强调销售良好的产品

这种颜色编码方式可以帮助用户快速识别产品的特性,提升信息传达效率。

6. 完整代码分析

让我们回顾完整的ProductList组件代码:

interface Product { image: Resource |string, title: string, price: string }
@Component
export struct ProductList {
    private products:Product[] = [
        { image: $r('app.media.phone'), title: '智能手表', price: '¥1299' },
        { image: $r('app.media.phone'), title: '无线耳机', price: '¥499' }
    ]

    build() {
        Column({ space: 20 }) // 外层 Column 控制列表垂直间距
             {

            ForEach(this.products, (item:Product) => {
                Row({ space: 16 }) // 每个列表项内部用 Row 水平排列
                   {

                    // 左侧图片
                    Image(item.image)
                        .width(80)
                        .height(80)
                        .objectFit(ImageFit.Cover)
                        .borderRadius(4)

                    // 右侧内容区域(垂直排列)
                    Column({ space: 8 }) {
                        Text(item.title)
                            .fontSize(16)
                            .fontWeight(500)
                            .textOverflow({ overflow: TextOverflow.Ellipsis })
                            .maxLines(1)

                        Text(item.price)
                            .fontSize(14)
                            .fontColor(0xFF4D4F53)

                        // 水平排列的标签(嵌套 Row)
                        Row({ space: 4 }) {
                            Text('新品')
                                .fontSize(12)
                                .padding({ top: 2, bottom: 2, left: 8, right: 8 })
                                .backgroundColor(0xFFF0F0)
                                .borderRadius(10)

                            Text('热卖')
                                .fontSize(12)
                                .padding({ top: 2, bottom: 2, left: 8, right: 8 })
                                .backgroundColor(0xFFE5F5FF)
                                .borderRadius(10)
                        }
                    }
                } .width('100%')
                .height(120)
                .padding(12)
                .backgroundColor(0xFFFFFF)
                .borderRadius(8)
                .shadow({ radius: 2, color: 0x05000000 })
            }, (item:Product) => item.title)
        }.width('100%')
        .padding(16)
    }
}

6.1 代码结构分析

  1. 接口定义:定义Product接口,描述产品数据结构
  2. 组件定义:使用@Component装饰器定义ProductList自定义组件
  3. 数据初始化:初始化products数组,包含两个产品示例
  4. 布局结构

    • 外层Column:垂直排列所有列表项
    • ForEach循环:遍历products数组,渲染每个产品
    • 列表项Row:水平排列图片和内容
    • 内容Column:垂直排列标题、价格和标签
    • 标签Row:水平排列多个标签

6.2 布局嵌套层次

本案例展示了多层嵌套布局的实现方式:

  1. 第一层:外层Column(垂直列表)
  2. 第二层:列表项Row(水平排列)
  3. 第三层:右侧内容Column(垂直排列)
  4. 第四层:标签Row(水平排列)

这种多层嵌套的布局结构能够实现复杂的界面设计,但也需要注意控制嵌套深度,避免过度嵌套导致性能问题。

6.3 链式调用的优势

在代码中,我们大量使用了链式调用来设置组件属性:

Image(item.image)
    .width(80)
    .height(80)
    .objectFit(ImageFit.Cover)
    .borderRadius(4)

链式调用的优势包括:

  • 代码简洁:避免重复写组件变量名
  • 可读性强:属性设置清晰可见
  • 易于修改:可以方便地添加或删除属性

7. 总结

通过本教程的两个部分,我们详细讲解了如何使用Column和Row组件的嵌套组合,创建一个垂直列表与水平操作栏相结合的复合布局


全栈若城
1 声望2 粉丝