[HarmonyOS NEXT 实战案例十] 电子书网格布局(上)
项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
1. 概述
本教程将详细讲解如何使用HarmonyOS NEXT中的GridRow和GridCol组件实现电子书网格布局。通过网格布局,我们可以以美观、规整的方式展示各种电子书信息,为用户提供良好的浏览体验。
本教程将涵盖以下内容:
- 电子书数据结构设计
- 数据准备
- 整体布局实现
- GridRow和GridCol组件配置
- 电子书卡片实现
- 布局效果分析
2. 数据结构设计
首先,我们需要定义电子书的数据结构,包含电子书的基本信息:
// 电子书数据类型
export interface BookType {
id: number; // 书籍ID
title: string; // 书名
cover: Resource; // 封面图片
author: string; // 作者
category: string; // 分类
rating: number; // 评分
price: number; // 价格
isFree: boolean; // 是否免费
isNew: boolean; // 是否新书
description: string; // 简介
}
3. 数据准备
接下来,我们准备一些示例数据用于展示:
// 电子书数据
private books: BookType[] = [
{
id: 1,
title: '人工智能导论',
cover: $r('app.media.book_ai'),
author: '李明',
category: '计算机',
rating: 4.8,
price: 68,
isFree: false,
isNew: true,
description: '本书全面介绍了人工智能的基本概念、发展历史、核心技术和应用领域,适合人工智能初学者阅读。'
},
{
id: 2,
title: '数据结构与算法',
cover: $r('app.media.book_algorithm'),
author: '张伟',
category: '计算机',
rating: 4.9,
price: 78,
isFree: false,
isNew: false,
description: '本书详细讲解了常用的数据结构和算法,包括数组、链表、栈、队列、树、图、排序和搜索算法等。'
},
{
id: 3,
title: '深度学习实战',
cover: $r('app.media.book_deep_learning'),
author: '王芳',
category: '计算机',
rating: 4.7,
price: 88,
isFree: false,
isNew: true,
description: '本书通过实际案例讲解深度学习的原理和应用,包括神经网络、卷积神经网络、循环神经网络等。'
},
{
id: 4,
title: '经济学原理',
cover: $r('app.media.book_economics'),
author: '刘强',
category: '经济',
rating: 4.6,
price: 0,
isFree: true,
isNew: false,
description: '本书介绍了经济学的基本原理和概念,包括供需关系、市场结构、宏观经济政策等。'
},
{
id: 5,
title: '心理学入门',
cover: $r('app.media.book_psychology'),
author: '陈静',
category: '心理',
rating: 4.5,
price: 58,
isFree: false,
isNew: false,
description: '本书介绍了心理学的基本理论和研究方法,包括认知心理学、发展心理学、社会心理学等。'
},
{
id: 6,
title: '现代文学赏析',
cover: $r('app.media.book_literature'),
author: '赵红',
category: '文学',
rating: 4.4,
price: 0,
isFree: true,
isNew: false,
description: '本书精选了现代文学作品进行赏析,包括小说、诗歌、散文等多种体裁。'
},
{
id: 7,
title: '健康生活指南',
cover: $r('app.media.book_health'),
author: '孙健',
category: '健康',
rating: 4.3,
price: 48,
isFree: false,
isNew: true,
description: '本书提供了健康生活的指导和建议,包括饮食、运动、心理健康等方面。'
},
{
id: 8,
title: '旅行摄影技巧',
cover: $r('app.media.book_photography'),
author: '吴光',
category: '摄影',
rating: 4.7,
price: 68,
isFree: false,
isNew: false,
description: '本书介绍了旅行摄影的技巧和方法,包括构图、光线、后期处理等方面。'
},
{
id: 9,
title: '烹饪艺术',
cover: $r('app.media.book_cooking'),
author: '郑厨',
category: '美食',
rating: 4.8,
price: 0,
isFree: true,
isNew: true,
description: '本书介绍了烹饪的基本技巧和方法,包括中餐、西餐、甜点等多种菜系。'
},
{
id: 10,
title: '投资理财基础',
cover: $r('app.media.book_finance'),
author: '黄金',
category: '金融',
rating: 4.5,
price: 58,
isFree: false,
isNew: false,
description: '本书介绍了投资理财的基本知识和方法,包括股票、基金、债券等投资工具。'
}
];
4. 布局实现
4.1 整体布局结构
我们将使用Column作为最外层容器,包含顶部搜索栏、分类标签栏和电子书网格列表:
build() {
Column() {
// 顶部搜索栏
this.SearchBar()
// 分类标签栏
this.CategoryTabs()
// 电子书网格列表
this.BookGrid()
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
4.2 顶部搜索栏
@Builder
private SearchBar() {
Row() {
// 搜索框
Row() {
Image($r('app.media.ic_search'))
.width(20)
.height(20)
.margin({ right: 8 })
TextInput({ placeholder: '搜索书名、作者' })
.layoutWeight(1)
.backgroundColor('transparent')
.placeholderColor('#999999')
.fontSize(14)
.height('100%')
}
.width('85%')
.height(40)
.backgroundColor(Color.White)
.borderRadius(20)
.padding({ left: 12, right: 12 })
// 筛选按钮
Image($r('app.media.ic_filter'))
.width(24)
.height(24)
.margin({ left: 12 })
}
.width('100%')
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
.backgroundColor('#673AB7')
}
4.3 分类标签栏
@State currentCategory: string = '推荐';
private categories: string[] = ['推荐', '计算机', '经济', '文学', '心理', '健康', '摄影', '美食', '金融'];
@Builder
private CategoryTabs() {
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.categories, (category: string) => {
Text(category)
.fontSize(14)
.fontColor(this.currentCategory === category ? '#673AB7' : '#666666')
.fontWeight(this.currentCategory === category ? FontWeight.Bold : FontWeight.Normal)
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
.backgroundColor(this.currentCategory === category ? '#EDE7F6' : 'transparent')
.borderRadius(16)
.margin({ right: 8 })
.onClick(() => {
this.currentCategory = category;
})
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
}
4.4 电子书网格列表
这是本教程的核心部分,我们使用GridRow和GridCol组件实现电子书网格列表:
@Builder
private BookGrid() {
Scroll() {
Column() {
// 新书上架标题
Row() {
Text('新书上架')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, top: 16, bottom: 8 })
// 新书上架横向滚动列表
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.getNewBooks(), (book: BookType) => {
this.NewBookCard(book)
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
.margin({ bottom: 16 })
// 免费好书标题
Row() {
Text('免费好书')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 8 })
// 免费好书横向滚动列表
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.getFreeBooks(), (book: BookType) => {
this.FreeBookCard(book)
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
.margin({ bottom: 16 })
// 全部书籍标题
Row() {
Text('全部书籍')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 8 })
// 使用GridRow和GridCol实现网格布局
GridRow({
columns: { xs: 2, sm: 3, md: 4, lg: 5 },
gutter: { x: 16, y: 16 }
}) {
ForEach(this.books, (book: BookType) => {
GridCol() {
this.BookCard(book)
}
})
}
.width('100%')
.padding(16)
}
.width('100%')
}
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Vertical)
.width('100%')
.layoutWeight(1)
}
4.5 电子书卡片实现
// 新书卡片
@Builder
private NewBookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width(120)
.height(160)
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 新书标签
Text('新书')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#FF4081')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
.width(120)
.height(160)
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 4 })
}
.margin({ right: 12 })
}
// 免费书籍卡片
@Builder
private FreeBookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width(120)
.height(160)
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 免费标签
Text('免费')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#4CAF50')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
.width(120)
.height(160)
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 4 })
}
.margin({ right: 12 })
}
// 标准书籍卡片
@Builder
private BookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width('100%')
.aspectRatio(0.75) // 3:4的宽高比
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 免费或新书标签
if (book.isFree) {
Text('免费')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#4CAF50')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
} else if (book.isNew) {
Text('新书')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#FF4081')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
}
.width('100%')
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
.margin({ top: 4 })
// 评分和价格
Row() {
Row() {
Image($r('app.media.ic_star'))
.width(12)
.height(12)
.margin({ right: 4 })
Text(book.rating.toString())
.fontSize(12)
.fontColor('#FFC107')
}
Blank()
Text(book.isFree ? '免费' : `¥${book.price}`)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor(book.isFree ? '#4CAF50' : '#FF5722')
}
.width('100%')
.margin({ top: 4 })
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(8)
.padding(8)
}
4.6 辅助方法
// 获取新书列表
private getNewBooks(): BookType[] {
return this.books.filter(book => book.isNew);
}
// 获取免费书籍列表
private getFreeBooks(): BookType[] {
return this.books.filter(book => book.isFree);
}
5. GridRow和GridCol配置详解
在本案例中,我们使用了GridRow和GridCol组件实现网格布局。下面详细解析其配置:
5.1 GridRow配置
GridRow({
columns: { xs: 2, sm: 3, md: 4, lg: 5 },
gutter: { x: 16, y: 16 }
})
-
columns
:定义不同屏幕尺寸下的列数xs: 2
:极小屏幕(如小型手机)显示2列sm: 3
:小屏幕(如大型手机)显示3列md: 4
:中等屏幕(如平板)显示4列lg: 5
:大屏幕(如桌面)显示5列
-
gutter
:定义网格间的间距x: 16
:水平间距为16像素y: 16
:垂直间距为16像素
5.2 GridCol配置
在本案例中,我们使用了默认的GridCol配置,没有指定span属性,这意味着每个电子书卡片占据一个网格单元。
GridCol() {
this.BookCard(book)
}
如果需要某些电子书卡片占据更多的空间,可以通过span属性进行配置:
GridCol({
span: { xs: 2, sm: 1, md: 1, lg: 1 }
}) {
this.BookCard(book)
}
这样配置后,在极小屏幕(xs)上,该电子书卡片会占据2列,而在其他屏幕尺寸上占据1列。
6. 布局效果分析
6.1 响应式布局
通过GridRow的columns配置,我们实现了响应式布局,使应用能够适应不同屏幕尺寸的设备:
屏幕尺寸 | 列数 | 效果 |
---|---|---|
极小屏幕(xs) | 2列 | 每行显示2个电子书卡片 |
小屏幕(sm) | 3列 | 每行显示3个电子书卡片 |
中等屏幕(md) | 4列 | 每行显示4个电子书卡片 |
大屏幕(lg) | 5列 | 每行显示5个电子书卡片 |
6.2 网格间距
通过GridRow的gutter配置,我们设置了网格间的间距为16像素,使布局更加美观、清晰。
6.3 电子书卡片设计
我们设计了三种电子书卡片:
-
新书卡片:用于横向滚动的新书上架区域
- 固定宽度为120像素
- 显示新书标签
- 显示书名和作者
-
免费书籍卡片:用于横向滚动的免费好书区域
- 固定宽度为120像素
- 显示免费标签
- 显示书名和作者
-
标准书籍卡片:用于网格布局的全部书籍区域
- 宽度自适应
- 根据书籍属性显示新书或免费标签
- 显示书名、作者、评分和价格
这种设计使用户能够快速获取电子书的关键信息,便于做出选择。
7. GridRow和GridCol组件详解
7.1 GridRow组件
GridRow是HarmonyOS NEXT提供的网格行容器组件,用于创建网格布局。它具有以下主要属性:
属性 | 类型 | 描述 |
---|---|---|
columns | number | { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | 当前行的总列数 |
gutter | number | { x?: number, y?: number } | 栅格间隔 |
breakpoints | { value: number, reference: BreakpointsReference }[] | 自定义断点值 |
7.2 GridCol组件
GridCol是HarmonyOS NEXT提供的网格列容器组件,用于在GridRow中创建网格列。它具有以下主要属性:
属性 | 类型 | 描述 |
---|---|---|
span | number | { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | 列宽度 |
offset | number | { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | 列偏移量 |
order | number | { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } | 列顺序 |
8. 完整代码
@Entry
@Component
struct EBookGrid {
// 电子书数据类型
interface BookType {
id: number; // 书籍ID
title: string; // 书名
cover: Resource; // 封面图片
author: string; // 作者
category: string; // 分类
rating: number; // 评分
price: number; // 价格
isFree: boolean; // 是否免费
isNew: boolean; // 是否新书
description: string; // 简介
}
// 电子书数据
private books: BookType[] = [
{
id: 1,
title: '人工智能导论',
cover: $r('app.media.book_ai'),
author: '李明',
category: '计算机',
rating: 4.8,
price: 68,
isFree: false,
isNew: true,
description: '本书全面介绍了人工智能的基本概念、发展历史、核心技术和应用领域,适合人工智能初学者阅读。'
},
{
id: 2,
title: '数据结构与算法',
cover: $r('app.media.book_algorithm'),
author: '张伟',
category: '计算机',
rating: 4.9,
price: 78,
isFree: false,
isNew: false,
description: '本书详细讲解了常用的数据结构和算法,包括数组、链表、栈、队列、树、图、排序和搜索算法等。'
},
{
id: 3,
title: '深度学习实战',
cover: $r('app.media.book_deep_learning'),
author: '王芳',
category: '计算机',
rating: 4.7,
price: 88,
isFree: false,
isNew: true,
description: '本书通过实际案例讲解深度学习的原理和应用,包括神经网络、卷积神经网络、循环神经网络等。'
},
{
id: 4,
title: '经济学原理',
cover: $r('app.media.book_economics'),
author: '刘强',
category: '经济',
rating: 4.6,
price: 0,
isFree: true,
isNew: false,
description: '本书介绍了经济学的基本原理和概念,包括供需关系、市场结构、宏观经济政策等。'
},
{
id: 5,
title: '心理学入门',
cover: $r('app.media.book_psychology'),
author: '陈静',
category: '心理',
rating: 4.5,
price: 58,
isFree: false,
isNew: false,
description: '本书介绍了心理学的基本理论和研究方法,包括认知心理学、发展心理学、社会心理学等。'
},
{
id: 6,
title: '现代文学赏析',
cover: $r('app.media.book_literature'),
author: '赵红',
category: '文学',
rating: 4.4,
price: 0,
isFree: true,
isNew: false,
description: '本书精选了现代文学作品进行赏析,包括小说、诗歌、散文等多种体裁。'
},
{
id: 7,
title: '健康生活指南',
cover: $r('app.media.book_health'),
author: '孙健',
category: '健康',
rating: 4.3,
price: 48,
isFree: false,
isNew: true,
description: '本书提供了健康生活的指导和建议,包括饮食、运动、心理健康等方面。'
},
{
id: 8,
title: '旅行摄影技巧',
cover: $r('app.media.book_photography'),
author: '吴光',
category: '摄影',
rating: 4.7,
price: 68,
isFree: false,
isNew: false,
description: '本书介绍了旅行摄影的技巧和方法,包括构图、光线、后期处理等方面。'
},
{
id: 9,
title: '烹饪艺术',
cover: $r('app.media.book_cooking'),
author: '郑厨',
category: '美食',
rating: 4.8,
price: 0,
isFree: true,
isNew: true,
description: '本书介绍了烹饪的基本技巧和方法,包括中餐、西餐、甜点等多种菜系。'
},
{
id: 10,
title: '投资理财基础',
cover: $r('app.media.book_finance'),
author: '黄金',
category: '金融',
rating: 4.5,
price: 58,
isFree: false,
isNew: false,
description: '本书介绍了投资理财的基本知识和方法,包括股票、基金、债券等投资工具。'
}
];
@State currentCategory: string = '推荐';
private categories: string[] = ['推荐', '计算机', '经济', '文学', '心理', '健康', '摄影', '美食', '金融'];
build() {
Column() {
// 顶部搜索栏
this.SearchBar()
// 分类标签栏
this.CategoryTabs()
// 电子书网格列表
this.BookGrid()
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
@Builder
private SearchBar() {
Row() {
// 搜索框
Row() {
Image($r('app.media.ic_search'))
.width(20)
.height(20)
.margin({ right: 8 })
TextInput({ placeholder: '搜索书名、作者' })
.layoutWeight(1)
.backgroundColor('transparent')
.placeholderColor('#999999')
.fontSize(14)
.height('100%')
}
.width('85%')
.height(40)
.backgroundColor(Color.White)
.borderRadius(20)
.padding({ left: 12, right: 12 })
// 筛选按钮
Image($r('app.media.ic_filter'))
.width(24)
.height(24)
.margin({ left: 12 })
}
.width('100%')
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
.backgroundColor('#673AB7')
}
@Builder
private CategoryTabs() {
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.categories, (category: string) => {
Text(category)
.fontSize(14)
.fontColor(this.currentCategory === category ? '#673AB7' : '#666666')
.fontWeight(this.currentCategory === category ? FontWeight.Bold : FontWeight.Normal)
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
.backgroundColor(this.currentCategory === category ? '#EDE7F6' : 'transparent')
.borderRadius(16)
.margin({ right: 8 })
.onClick(() => {
this.currentCategory = category;
})
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
}
@Builder
private BookGrid() {
Scroll() {
Column() {
// 新书上架标题
Row() {
Text('新书上架')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, top: 16, bottom: 8 })
// 新书上架横向滚动列表
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.getNewBooks(), (book: BookType) => {
this.NewBookCard(book)
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
.margin({ bottom: 16 })
// 免费好书标题
Row() {
Text('免费好书')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 8 })
// 免费好书横向滚动列表
Scroll(ScrollDirection.Horizontal) {
Row() {
ForEach(this.getFreeBooks(), (book: BookType) => {
this.FreeBookCard(book)
})
}
.padding({ left: 16, right: 16 })
}
.scrollBar(BarState.Off)
.width('100%')
.margin({ bottom: 16 })
// 全部书籍标题
Row() {
Text('全部书籍')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Blank()
Text('查看更多 >')
.fontSize(14)
.fontColor('#673AB7')
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 8 })
// 使用GridRow和GridCol实现网格布局
GridRow({
columns: { xs: 2, sm: 3, md: 4, lg: 5 },
gutter: { x: 16, y: 16 }
}) {
ForEach(this.books, (book: BookType) => {
GridCol() {
this.BookCard(book)
}
})
}
.width('100%')
.padding(16)
}
.width('100%')
}
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Vertical)
.width('100%')
.layoutWeight(1)
}
// 新书卡片
@Builder
private NewBookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width(120)
.height(160)
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 新书标签
Text('新书')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#FF4081')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
.width(120)
.height(160)
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 4 })
}
.margin({ right: 12 })
}
// 免费书籍卡片
@Builder
private FreeBookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width(120)
.height(160)
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 免费标签
Text('免费')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#4CAF50')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
.width(120)
.height(160)
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width(120)
.margin({ top: 4 })
}
.margin({ right: 12 })
}
// 标准书籍卡片
@Builder
private BookCard(book: BookType) {
Column() {
// 书籍封面
Stack() {
Image(book.cover)
.width('100%')
.aspectRatio(0.75) // 3:4的宽高比
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 免费或新书标签
if (book.isFree) {
Text('免费')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#4CAF50')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
} else if (book.isNew) {
Text('新书')
.fontSize(12)
.fontColor(Color.White)
.backgroundColor('#FF4081')
.borderRadius(4)
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.position({ x: 8, y: 8 })
}
}
.width('100%')
// 书名
Text(book.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#333333')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
.margin({ top: 8 })
// 作者
Text(book.author)
.fontSize(12)
.fontColor('#666666')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
.margin({ top: 4 })
// 评分和价格
Row() {
Row() {
Image($r('app.media.ic_star'))
.width(12)
.height(12)
.margin({ right: 4 })
Text(book.rating.toString())
.fontSize(12)
.fontColor('#FFC107')
}
Blank()
Text(book.isFree ? '免费' : `¥${book.price}`)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor(book.isFree ? '#4CAF50' : '#FF5722')
}
.width('100%')
.margin({ top: 4 })
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(8)
.padding(8)
}
// 获取新书列表
private getNewBooks(): BookType[] {
return this.books.filter(book => book.isNew);
}
// 获取免费书籍列表
private getFreeBooks(): BookType[] {
return this.books.filter(book => book.isFree);
}
}
9. 总结
本教程详细讲解了如何使用HarmonyOS NEXT中的GridRow和GridCol组件实现电子书网格布局。通过合理的数据结构设计、精心的UI设计和灵活的GridRow配置,我们实现了一个美观、响应式的电子书展示页面。
主要内容包括:
- 电子书数据结构设计和数据准备
- 整体布局实现,包括顶部搜索栏、分类标签栏和电子书网格列表
- GridRow和GridCol组件的配置和使用
- 电子书卡片的设计和实现,包括新书卡片、免费书籍卡片和标准书籍卡片
- 布局效果分析
- 0回答
- 3粉丝
- 0关注
- [HarmonyOS NEXT 实战案例十] 电子书网格布局(下)
- [HarmonyOS NEXT 实战案例四] 天气应用网格布局(上)
- [HarmonyOS NEXT 实战案例六] 餐饮菜单网格布局(上)
- [HarmonyOS NEXT 实战案例七] 健身课程网格布局(上)
- [HarmonyOS NEXT 实战案例九] 旅游景点网格布局(上)
- [HarmonyOS NEXT 实战案例十四] 任务管理看板网格布局(上)
- [HarmonyOS NEXT 实战案例十八] 日历日程视图网格布局(上)
- [HarmonyOS NEXT 实战案例十七] 设置选项列表网格布局(上)
- [HarmonyOS NEXT 实战案例五] 社交应用照片墙网格布局(上)
- [HarmonyOS NEXT 实战案例一] 电商首页商品网格布局(上)
- [HarmonyOS NEXT 实战案例十三] 音乐播放器网格布局(上)
- [HarmonyOS NEXT 实战案例八] 电影票务网格布局(上)
- [HarmonyOS NEXT 实战案例十二] 健康数据仪表盘网格布局(上)
- [HarmonyOS NEXT 实战案例十六] 个人资料卡片网格布局(上)
- [HarmonyOS NEXT 实战案例十一] 智能家居控制面板网格布局(上)