#HarmonyOS NEXT体验官#HarmoneyOS NEXT应用开发实战《仿xhs首页列表与详情》 原创 原创
前言
随着鸿蒙next星河版系统的公布,越来越多的大厂都纷纷下场加入鸿蒙应用开发中,作为第一批响应鸿蒙原生开发的应用,小红书的市场份额也不言而喻,现阶段我们大部分开发对鸿蒙的基础知识已经掌握,那么我们在开发中要自己实现小红书的功能要如何去做呢?
大部分情况如下所示
1. 打开百度
2. 输入鸿蒙仿小红书
3. cccv提交代码一气呵成
可今天,看了我这篇文章,你自己就是一个团队,分分钟拿下某书,为你的大牛之路添砖加瓦。。。
今天我们就在HamoneyOS中先实现一个小红书首页和详情。
效果介绍
首先就是我们的首页效果
1首页分为头部分类
2二级分类
3底部功能模块
当我们点击列表中的某一条数据,跳转到详情页(如下图)
1详情页分为顶部用户信息展示模块2图文展示
3底部点赞发言模块
那我们的需求已经很明确了,接下来我们来讲解如何通过代码来实现我们对应页面的效果
代码实现
首页的头部分类跟二级分类,都要用到ArkUi的Tabs组件
首先我们需要先定义好tabs需要显示的数据我们通过创建多个tabcontent 然后在tabBar中放入页签
然后我们需要给tabs创建一个自定义的页签,来实现我们点击时组件的切换效果
@Builder TabBuilder(index: number, name: string) {
Column() {
Text(name)
.fontColor(this.currIndex === index ? this.selectedFontColor : this.fontColor)
.fontSize(this.currIndex === index ?16:14)
.fontWeight(this.currIndex === index ? 500 : 400)
.lineHeight(22)
.margin({ top: 17, bottom: 7 })
Divider()
.lineCap(LineCapStyle.Round)
.width(30)
.strokeWidth(2)
.color(Color.Red)
.opacity(this.currIndex === index ? 1 : 0)
}
.padding({left:10,right:10})
}
之后因为我们的列表是一行两列所以我们还需要使用Grid 组件来实现列表
我们用@Builder 来声明,方便我们自由引用(列表展示如下)
@Builder
buildList() {
Grid() {
ForEach(this.channelList, (item: HomeBean) => {
GridItem(){
this.NewsItem(item)
}
})
}
.padding(10)
.columnsGap(10)
.rowsGap(10)
.columnsTemplate('1fr 1fr')
.height('100%')
.width('100%')
.align(Alignment.TopStart)
}
因为grid 组件需要显示多条,现在开始定义一条的样式实现如下
(分别有图片,头像,昵称,icon ,点赞数)
@Builder NewsItem(item:HomeBean){
Column(){
Image(item.imgUrl)
.objectFit(ImageFit.Fill)
.height(190)
.width('100%')
.interpolation(ImageInterpolation.High)
.borderRadius({topLeft:5,topRight:5})
Text(item.title).fontSize(12).fontWeight(FontWeight.Bold).margin({top:8,left:5})
.textOverflow({overflow:TextOverflow.Ellipsis})
.maxLines(2)
.fontColor("#333333")
Row(){
Image(item.icon).width(20)
.height(20).borderRadius(10)
.interpolation(ImageInterpolation.High)
Text(item.name).fontSize(12).fontColor("#999999").margin({left:5})
Blank()
Image($r('app.media.xihuan'))
.width(15)
.height(15)
.interpolation(ImageInterpolation.High)
Text(String(item.like)).fontSize(12)
.fontColor("#999999")
}
.margin({top:10})
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
}
.backgroundColor(Color.White)
.borderRadius(10)
.width('100%')
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Start)
.onClick(()=>{
//点击事件处理
router.pushUrl({url:'pages/DetailsPage',params:{
data:JSON.stringify(item)
}})
})
}
之后我们把定义的两个布局跟tabs 进行结合
Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
TabContent() {
Column(){
this.buildList()
}
.layoutWeight(1)
.backgroundColor("#F9F9F9")
.width('100%')
.height('100%')
}.tabBar(this.TabBuilder(0, 'green'))
}
.vertical(false)
.barMode(BarMode.Fixed)
.barWidth(360)
.barHeight(56)
.animationDuration(400)
.onChange((index: number) => {
this.currentIndex = index
})
.width(360)
.height(296)
.margin({ top: 52 })
.backgroundColor('#F1F3F5')
这样我们的页面框架就搭好了(展示如下)
现在我们创建DataModel 开始填充我们页面框架需要展示的数据,数据内容可以自己根据需求制定
先定义一个实体类
export class HomeBean {
imgUrl:string
title:string
icon:string
name:string
like:string
msg:string
constructor( imgUrl:string,
title:string,
icon:string,
name:string,
like:string,
msg:string) {
this.imgUrl=imgUrl
this.title=title
this.icon=icon
this.name=name
this.like=like
this.msg=msg
}
}
然后我们创建DataModel 数据源,填充数据
import { HomeBean } from '../entity/HomeBean'
export class DataModel {
getHome():Array<HomeBean>{
let list:HomeBean[]=[
new HomeBean(
"https://tse3-mm.cn.bing.net/th/id/OIP-C.ZgeX3Yk1FFFuPxKZmNgoZwHaI0?w=146&h=180&c=7&r=0&o=5&dpr=2&pid=1.7"
,"彩色日记",
"https://tse3-mm.cn.bing.net/th/id/OIP-C.Fyq_wIdHP0_3aaHJuz1w_wAAAA?w=140&h=203&c=7&r=0&o=5&dpr=2&pid=1.7"
,"南北芝麻糊",
"1805","使用彩铅、水彩、马克笔等画材,在日记本上不仅仅书写文字,还配以当日心情、天气或重要事件相关的彩色插画。这样,每一天的记录都成为了一幅独一无二的艺术作品,颜色反映了当天的情绪和体验。"),
new HomeBean(
"https://tse2-mm.cn.bing.net/th/id/OIP-C.myAvQCC58qS6DDa6lY_x4QHaHm?w=217&h=220&c=7&r=0&o=5&dpr=2&pid=1.7"
,"一定要看到最后,古董鉴赏",
"https://tse3-mm.cn.bing.net/th/id/OIP-C.ThlIZCylEwsmbz2ZGAYglAAAAA?w=199&h=199&c=7&r=0&o=5&dpr=2&pid=1.7"
,"类哥累不累",
"988","鉴赏古瓷:看这一篇就够了. 中国古瓷器的历史悠久,青瓷的制作可追溯到两千多年前的西周时期。. 在古瓷器制作过程中包括选料、加工、制胎、上釉等多道工序。")
]
return list
}
}
export default new DataModel()
接下来只需要在Page页面中引入我们定义的数据源
private channelList:HomeBean[]=DataModel.getHome()
这样我们的页面就可以展示数据了
详情页面我们只需要在列表条目上添加一个点击事件,事件触发的时候把数据传过去就可以了(代码实现如下)
我们通过router ->pushUrl ->params 传递参数过去,定义key为data
.onClick(()=>{
//点击事件处理
router.pushUrl({url:'详情页面路由',params:{
data:JSON.stringify(item)
}})
既然涉及到了跳转,那我们就需要创建一个新的详情页面,然后在router中填写相应的路由
在详情页面我们用data的key去接收数据
先定义我们接收数据的实体类型的参数
@State dataDetail:HomeBean=null
然后接收数据,在组件的生命周期中赋值给他
aboutToAppear(){
let order:string= router.getParams()['data']
let data:HomeBean= JSON.parse(order)
this.dataDetail=data
}
接下来我们添加头部模块并填充图文数据
效果如下
Column() {
Row(){
Image($r('app.media.back'))
.width(25)
.height(25)
.onClick(()=>{
router.back()
})
Image(this.dataDetail.icon)
.height(30)
.width(30)
.borderRadius(20)
.margin({left:10})
.interpolation(ImageInterpolation.High)
Text(this.dataDetail.name)
.margin({left:10})
Blank()
Text("关注")
.border({width:1,color:Color.Red,radius:20})
.padding({left:7,right:7,top:3,bottom:3})
.margin({right:10})
.fontSize(14)
.fontColor(Color.Red)
Image($r('app.media.fenxiang'))
.width(25)
.height(25)
.margin({right:25})
.interpolation(ImageInterpolation.High)
}
.width('100%')
.margin({top:10})
Image(this.dataDetail.imgUrl)
.height(300)
.width('100%')
.margin({top:20})
Text(this.dataDetail.title)
.margin({left:15,top:10})
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(this.dataDetail.msg)
.fontSize(16)
.margin({top:15})
.padding(10)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
好的,到这里我们的xhs首页,详情页面的效果就实现了,快去试一试吧!