[HarmonyOS NEXT 实战案例:新闻阅读应用] 基础篇 - 水平分割布局构建新闻阅读界面
[HarmonyOS NEXT 实战案例:新闻阅读应用] 基础篇 - 水平分割布局构建新闻阅读界面
项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
引言
新闻阅读应用是移动应用开发中的常见场景,用户通过这类应用获取最新资讯和内容。一个设计良好的新闻阅读界面需要清晰展示新闻分类和新闻列表,方便用户快速浏览和选择感兴趣的内容。本教程将详细讲解如何使用HarmonyOS NEXT的RowSplit
组件构建一个新闻阅读应用界面,通过水平分割布局将界面分为新闻分类标签和新闻列表区域。
组件概述
在本案例中,我们将使用以下HarmonyOS NEXT组件:
组件名称 | 功能描述 |
---|---|
RowSplit |
水平分割布局容器,将界面分为左右两部分 |
Column |
垂直布局容器,用于垂直排列子组件 |
List |
列表容器,用于显示新闻列表 |
ListItem |
列表项组件,用于显示单条新闻 |
Row |
水平布局容器,用于水平排列子组件 |
Text |
文本组件,用于显示新闻标题、内容等 |
Image |
图片组件,用于显示新闻缩略图 |
Button |
按钮组件,用于新闻分类标签 |
ForEach |
循环渲染组件,用于渲染新闻分类和新闻列表 |
数据模型
在实现界面之前,我们首先定义新闻数据的模型:
class NewsItem {
title: string;
source: string;
time: string;
imageUrl: Resource;
category: string;
constructor(title: string, source: string, time: string, imageUrl: Resource, category: string) {
this.title = title;
this.source = source;
this.time = time;
this.imageUrl = imageUrl;
this.category = category;
}
}
这个模型包含新闻的标题、来源、时间、图片和分类信息。
代码实现
组件结构
首先,我们定义了一个名为NewsReaderExample
的自定义组件,并在其中定义了新闻分类和新闻数据:
@Component
export struct NewsReaderExample {
@State selectedCategory: string = '推荐';
private categories: string[] = ['推荐', '科技', '体育', '财经', '娱乐', '健康'];
@State newsData: NewsItem[] = [
new NewsItem('HarmonyOS NEXT发布,带来全新的分布式体验', '科技日报', '10分钟前', $r('app.media.big30'), '科技'),
new NewsItem('全国科技创新大会在北京召开', '新闻网', '30分钟前', $r('app.media.big31'), '科技'),
new NewsItem('2023年全球智能手机市场分析报告', '科技评论', '1小时前', $r('app.media.big32'), '科技'),
new NewsItem('国足最新一期集训名单公布', '体育新闻', '2小时前', $r('app.media.big33'), '体育'),
new NewsItem('NBA季后赛最新战报', '体育周刊', '3小时前', $r('app.media.big34'), '体育'),
new NewsItem('央行发布最新货币政策报告', '财经日报', '4小时前', $r('app.media.big35'), '财经'),
new NewsItem('A股市场今日行情分析', '证券时报', '5小时前', $r('app.media.big36'), '财经'),
new NewsItem('某流量明星最新电影票房破10亿', '娱乐周刊', '6小时前', $r('app.media.big37'), '娱乐'),
new NewsItem('夏季养生指南:如何科学防暑', '健康时报', '7小时前', $r('app.media.big38'), '健康')
];
build() {
// 组件内容
}
}
在这个组件中:
selectedCategory
状态变量用于跟踪当前选中的新闻分类categories
数组包含所有可用的新闻分类newsData
状态变量包含所有新闻数据
外层容器
我们使用Column
组件作为最外层容器,包含标题文本和主要内容区域:
Column() {
Text('新闻阅读应用布局')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
RowSplit() {
// RowSplit内容
}
.height(600)
}
.width('100%')
.padding(15)
外层Column
设置了宽度为100%和15的内边距,确保整个界面充分利用可用空间并与屏幕边缘有适当的间距。
水平分割布局
我们使用RowSplit
组件将界面分为左右两部分:
RowSplit() {
// 左侧新闻分类区域
Column() {
// 新闻分类内容
}
.width('25%')
.backgroundColor('#f5f5f5')
// 右侧新闻列表区域
Column() {
// 新闻列表内容
}
.width('75%')
}
.height(600)
在这个RowSplit
中:
- 左侧区域是新闻分类区域,占总宽度的25%,背景色为浅灰色
- 右侧区域是新闻列表区域,占总宽度的75%
- 整个
RowSplit
的高度设置为600像素
左侧新闻分类区域
左侧新闻分类区域使用Column
组件,包含一系列分类按钮:
Column() {
ForEach(this.categories, (category: string) => {
Button(category)
.width('90%')
.height(50)
.fontSize(16)
.margin({ top: 10 })
.borderRadius(8)
.backgroundColor(this.selectedCategory === category ? '#007DFF' : '#ffffff')
.fontColor(this.selectedCategory === category ? '#ffffff' : '#333333')
.onClick(() => {
this.selectedCategory = category;
})
})
}
.width('25%')
.backgroundColor('#f5f5f5')
.padding({ top: 10 })
在这个区域中:
- 使用
ForEach
循环渲染所有分类按钮 - 每个按钮的宽度为父容器的90%,高度为50像素,上边距为10像素,圆角为8像素
- 根据
selectedCategory
状态设置按钮的背景色和文字颜色 - 添加
onClick
事件处理器,在点击时更新selectedCategory
状态
右侧新闻列表区域
右侧新闻列表区域使用Column
组件,包含一个List
组件用于显示新闻列表:
Column() {
List() {
ForEach(this.newsData.filter(item => this.selectedCategory === '推荐' || item.category === this.selectedCategory), (item: NewsItem) => {
ListItem() {
this.NewsItemComponent(item)
}
.padding(10)
})
}
.width('100%')
.height('100%')
.divider({ strokeWidth: 1, color: '#f0f0f0', startMargin: 10, endMargin: 10 })
}
.width('75%')
在这个区域中:
- 使用
List
组件显示新闻列表 - 使用
ForEach
循环渲染符合当前选中分类的新闻项 - 使用
filter
方法过滤新闻数据,只显示当前选中分类的新闻(如果选中的是"推荐",则显示所有新闻) - 每个
ListItem
的内边距为10像素 List
组件的宽度和高度都设置为100%,确保充分利用可用空间- 添加分割线,线宽为1像素,颜色为浅灰色,左右边距为10像素
新闻项组件
为了显示单条新闻,我们定义了一个NewsItemComponent
方法:
@Builder
private NewsItemComponent(item: NewsItem) {
Row() {
Column() {
Text(item.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Row() {
Text(item.source)
.fontSize(14)
.fontColor('#666')
Text(item.time)
.fontSize(14)
.fontColor('#666')
.margin({ left: 10 })
}
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
Image(item.imageUrl)
.width(100)
.height(70)
.objectFit(ImageFit.Cover)
.borderRadius(5)
.margin({ left: 10 })
}
.width('100%')
}
在这个方法中:
- 使用
Row
组件作为最外层容器,包含新闻信息和新闻图片 - 左侧使用
Column
组件显示新闻标题、来源和时间- 新闻标题使用16像素的粗体字体,下边距为5像素
- 新闻来源和时间使用14像素的灰色字体,时间的左边距为10像素
Column
组件的layoutWeight
设置为1,确保它占据除图片外的所有可用空间alignItems
设置为HorizontalAlign.Start
,确保文本左对齐
- 右侧使用
Image
组件显示新闻图片- 图片宽度为100像素,高度为70像素
- 使用
objectFit(ImageFit.Cover)
确保图片填满区域并保持比例 - 圆角为5像素,左边距为10像素
布局分析
水平分割的应用
在本案例中,我们使用RowSplit
组件将界面分为左右两部分:
-
左侧区域(新闻分类区域):
- 占总宽度的25%
- 使用
Column
组件实现,垂直排列分类按钮 - 背景色为浅灰色,与右侧区域形成视觉区分
-
右侧区域(新闻列表区域):
- 占总宽度的75%
- 使用
Column
组件包含一个List
组件,显示新闻列表
这种水平分割的布局方式非常适合新闻阅读应用,使得用户可以方便地切换新闻分类,同时浏览当前分类的新闻列表。
列表的应用
在新闻列表区域,我们使用List
组件显示新闻列表:
List() {
ForEach(this.newsData.filter(item => this.selectedCategory === '推荐' || item.category === this.selectedCategory), (item: NewsItem) => {
ListItem() {
this.NewsItemComponent(item)
}
.padding(10)
})
}
.width('100%')
.height('100%')
.divider({ strokeWidth: 1, color: '#f0f0f0', startMargin: 10, endMargin: 10 })
List
组件的特点是可以高效地显示大量数据,并支持滚动和分割线等功能。在这个例子中,我们使用divider
属性添加分割线,使新闻项之间有明确的视觉分隔。
循环渲染的应用
在本案例中,我们使用ForEach
组件实现循环渲染,用于渲染新闻分类按钮和新闻列表项:
// 渲染新闻分类按钮
ForEach(this.categories, (category: string) => {
Button(category)
// 按钮属性
})
// 渲染新闻列表项
ForEach(this.newsData.filter(item => this.selectedCategory === '推荐' || item.category === this.selectedCategory), (item: NewsItem) => {
ListItem() {
this.NewsItemComponent(item)
}
.padding(10)
})
ForEach
组件接收一个数组和一个回调函数,对数组中的每个元素调用回调函数来渲染对应的组件。在新闻列表的例子中,我们还使用filter
方法过滤数据,只显示符合当前选中分类的新闻。
构建器的应用
在本案例中,我们使用@Builder
装饰器定义了一个NewsItemComponent
方法,用于构建新闻项组件:
@Builder
private NewsItemComponent(item: NewsItem) {
// 组件内容
}
@Builder
装饰器可以将一个方法转换为组件构建器,使得我们可以在多个地方重用相同的组件结构。在这个例子中,我们将新闻项的构建逻辑封装在NewsItemComponent
方法中,使代码更加模块化和可维护。
布局技巧
比例设置
在本案例中,我们使用百分比来设置左右区域的宽度(width('25%')
和width('75%')
),这样可以确保在不同屏幕尺寸下,左右区域的比例保持一致。
边距设置
我们为各个组件设置了适当的边距,确保界面布局美观:
- 外层
Column
设置了15的内边距,确保整个界面与屏幕边缘有适当的间距 - 分类按钮设置了10的上边距,确保按钮之间有适当的间距
- 新闻列表项设置了10的内边距,确保内容与边缘有适当的间距
- 新闻标题设置了5的下边距,确保标题和来源之间有适当的间距
- 新闻时间设置了10的左边距,确保来源和时间之间有适当的间距
- 新闻图片设置了10的左边距,确保文本和图片之间有适当的间距
文本样式设置
我们为不同类型的文本设置了不同的样式,使界面层次分明:
- 标题文本使用20像素的粗体字体,突出显示
- 新闻标题使用16像素的粗体字体,突出显示
- 新闻来源和时间使用14像素的灰色字体,区分主次信息
背景色设置
我们为左侧新闻分类区域设置了浅灰色背景(backgroundColor('#f5f5f5')
),与右侧新闻列表区域形成视觉区分,使界面结构更加清晰。
选中状态设置
我们为分类按钮设置了选中状态,使用户可以清楚地知道当前选中的是哪个分类:
.backgroundColor(this.selectedCategory === category ? '#007DFF' : '#ffffff')
.fontColor(this.selectedCategory === category ? '#ffffff' : '#333333')
当按钮被选中时,背景色变为蓝色,文字颜色变为白色;当按钮未被选中时,背景色为白色,文字颜色为深灰色。
总结
在本教程中,我们学习了如何使用HarmonyOS NEXT的RowSplit
组件构建一个新闻阅读应用界面。通过水平分割布局,我们将界面分为新闻分类区域和新闻列表区域,使得界面结构清晰,信息展示合理。
- 0回答
- 4粉丝
- 0关注
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 水平分割布局RowSplit详解
- [HarmonyOS NEXT 实战案例:旅行应用] 基础篇 - 水平分割布局打造旅行规划应用
- [HarmonyOS NEXT 实战案例:音乐播放器] 基础篇 - 水平分割布局打造音乐播放器界面
- [HarmonyOS NEXT 实战案例:聊天应用] 基础篇 - 垂直分割布局构建聊天界面
- [HarmonyOS NEXT 实战案例:健康应用] 基础篇 - 水平分割布局打造健康数据仪表盘
- [HarmonyOS NEXT 实战案例:文件管理器] 基础篇 - 垂直分割布局构建文件管理界面
- [HarmonyOS NEXT 实战案例一:SideBarContainer] 侧边栏容器实战:新闻阅读应用侧边栏布局 基础篇
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 打造现代化设置中心界面
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 垂直分割布局ColumnSplit详解
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 邮件应用布局设计
- [HarmonyOS NEXT 实战案例:分割布局] 进阶篇 - 三栏布局的嵌套与复杂界面构建
- [HarmonyOS NEXT 实战案例:新闻阅读应用] 高级篇 - 高级布局技巧与组件封装
- [HarmonyOS NEXT 实战案例:设置页面] 基础篇 - 垂直分割布局构建设置中心
- 94.[HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 三栏垂直分割布局
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 可调整分割比例的垂直布局