实现效果
需求描述:
- 对页面整体添加滚动效果
- 点击 logo 页面滚动至最顶端
- 完成 tab 切换功能: 点击视频 文字下方图为黑色,其余为白色; 点击视频文字白色高亮,其余黑色高亮
- 完成消息数提示展示
效果尺寸说明如下:
tabBar文字颜色 正常显示为 ‘#999’, 文字下方为黑色图时高亮显示为‘#fff’, 否则为 ‘#000’
tabBar下方图片 宽度 ‘100%’, 高度 55vp
消息数量提示 位置 position: {x: 25, y: -5}
代码如下:
interface BannerItem { //轮播图数组接口
imgUrl: ResourceStr,
imgTitle: string
}
interface ColumnarItem { // 内容精选接口
iconUrl: ResourceStr,
iconTitle: string
}
interface RecommendItem {// list列表接口
imgUrl: ResourceStr,
title: string,
createTime: string
}

@Entry
@Component
struct Index {
@State bannerList: BannerItem[] = [ // 轮播图数组
{imgUrl: $r('app.media.banner_01_1'), imgTitle: '谷歌杀入开源大模型,凭什么问鼎王座?'},
{imgUrl: $r('app.media.banner_01_3'), imgTitle: '微软牵手OpenAI劲敌!Mistral顶级大模型不再开源'},
{imgUrl: $r('app.media.banner_01_4'), imgTitle: '生成式AI会扼杀DevSecOps吗'},
{imgUrl: $r("app.media.banner_01_2"), imgTitle: '微软继续Linux化!sudo原生命令强势登录Windows'},
]
@State columnarList: ColumnarItem[] = [ // 内容精选数组
{iconUrl: $r('app.media.ic_01_1'), iconTitle: '内容精选'},
{iconUrl: $r('app.media.ic_01_2'), iconTitle: '学堂'},
{iconUrl: $r('app.media.ic_01_3'), iconTitle: '鸿蒙开发者社区'},
{iconUrl: $r('app.media.ic_01_4'), iconTitle: '博客'},
{iconUrl: $r('app.media.ic_01_5'), iconTitle: '企业培训'},
{iconUrl: $r('app.media.ic_01_6'), iconTitle: 'Next训练营'},
{iconUrl: $r('app.media.ic_01_7'), iconTitle: '精培'},
]
@State recommendList: RecommendItem[] = [ // list列表数组
{imgUrl: $r('app.media.list_02_1'), title: '字节一面:TCP和UDP可以使用同一个端口号吗?', createTime: '2024-03-05 10:07:22'},
{imgUrl: $r('app.media.list_02_2'), title: 'NoSQL:在高并发场景下,数据库和NoSQL如何做到互补?', createTime: '2024-03-05 10:03:17'},
{imgUrl: $r('app.media.list_02_3'), title: '处理大规模并发请求时如何设计和优化Python后端服务的架构和性能', createTime: '2024-03-05 10:03:09'},
{imgUrl: $r('app.media.list_02_4'), title: 'C++右值引用:解锁高效内存管理与性能优化的奥秘', createTime: '2024-03-05 09:55:00'},
{imgUrl: $r('app.media.list_02_5'), title: '现代分布式系统架构的权衡分析', createTime: '2024-03-05 09:52:57'},
]
// 轮播图自定义构建函数
@Builder BannerItem(img: ResourceStr, title: string) {
Stack() {
Image(img)
.width('100%')
Text(title)
.fontColor(Color.White)
.fontWeight(700)
.margin({left: 10, bottom: 30, right: 10})
.maxLines(1)
.textOverflow({overflow: TextOverflow.Ellipsis})
}
.alignContent(Alignment.BottomStart)
}
// 内容精选、、自定义构建函数
@Builder ColumnarItem(icon: ResourceStr, title: string) {
GridItem(){
Column() {
Image(icon)
.width(40)
Text(title)
.fontSize(14)
.fontColor('#666')
}
.justifyContent(FlexAlign.SpaceBetween)
.padding({left: 12, right: 12})
.height('100%')
}
}
// list列表自定义构建函数
@Builder RecommendItem(img: ResourceStr, title: string, createTime: string) {
ListItem() {
Row() {
Image(img)
.width(142)
.borderRadius(8)
Column() {
Text(title)
.fontSize(15)
.fontColor('#303030')
.maxLines(2)
.textOverflow({overflow: TextOverflow.Ellipsis})
Text(createTime)
.fontSize(12)
.fontColor('#c0c0c0')
}
.margin({left: 10})
.layoutWeight(1)
.height('100%')
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(HorizontalAlign.Start)
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height(110)
.padding({top: 15,bottom: 15})
.border({width: {bottom: 2}, color: '#f4f4f4'})
}
}
// 导航栏 状态变量 和 自定义构建函数
@State currentIndex: number = 0
@Builder tabBuilder(title:string,index:number){
if(index == 1){
Text(title)
.fontColor(this.currentIndex == index?'#fff':'#999')
.fontWeight(700)
}else if(index == 2){
Badge({
count:9,
position:{x:25,y:-5},
style:{}
}){
Text(title)
.fontColor(this.currentIndex == index?'#000':'#999')
.fontWeight(700)
}
}
else {
Text(title)
.fontColor(this.currentIndex == index?'#000':'#999')
.fontWeight(700)
}
}
scroller = new Scroller() // 点击回到顶部控制器
build() {
Stack(){
Image(this.currentIndex == 1?$r('app.media.bg_02_2'):$r('app.media.bg_02_1'))
.width('100%') //导航栏背景图
.height(55)
// 底部导航栏 和切换的内容
Tabs() {
TabContent(){
Column() {
Row() {
Image($r('app.media.hot_01'))
.width(60)
.onClick(()=>{ //点击回到顶部事件
this.scroller.scrollEdge(Edge.Top)
})
Row() {
Image($r('app.media.user_01'))
.width(20)
.margin({right: 15})
Image($r('app.media.more_01'))
.width(20)
}
}
.justifyContent(FlexAlign.SpaceBetween)
.padding({left:16, right: 16})
.width('100%')
.height(56)
Scroll(this.scroller) {
Column() {
Swiper() { //轮播图
ForEach(this.bannerList,(item: BannerItem) => {
this.BannerItem(item.imgUrl, item.imgTitle)
})
}
.loop(true)
.autoPlay(true)
.interval(3000)
.indicator(Indicator.dot()
.left(0)
.itemWidth(30)
.itemHeight(5)
.selectedItemWidth(30)
.selectedColor(Color.White)
)
Grid() { // 内容精选、、
ForEach(this.columnarList, (item: ColumnarItem) => {
this.ColumnarItem(item.iconUrl, item.iconTitle)
})
}
.scrollBar(BarState.Off)
.rowsTemplate('1fr')
.margin({top: 10})
.width('100%')
.height(65)
ColumnSplit() //
.margin({top: 20, bottom: 20})
.width('100%')
.height(4)
.backgroundColor('#fbfbfb')
Text('热门推荐')
.width('100%')
.padding({left: 10})
.fontSize(20)
.fontColor('#303030')
.fontWeight(700)
List() {
ForEach(this.recommendList, (item: RecommendItem) => {
this.RecommendItem(item.imgUrl, item.title, item.createTime)
})
}
.padding({left:10, right: 10, bottom: 20})
}
}
.layoutWeight(1)
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
}
.tabBar(this.tabBuilder('首页',0))
TabContent(){
Column() {
Image($r('app.media.banner_01_4'))
.height('100%')
}
.width('100%')
.height('100%')
}
.tabBar(this.tabBuilder('视频',1))
TabContent(){
Column() {
Text('待完成---消息')
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
.tabBar(this.tabBuilder('消息',2))
TabContent(){
Column() {
Text('待完成---我的')
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
.tabBar(this.tabBuilder('我的',3))
}
.barPosition(BarPosition.End) //导航栏在底部
.animationDuration(0)
.onChange((index)=>{ // 控制字体亮度的事件
this.currentIndex = index
})
}
.alignContent(Alignment.Bottom)
}
}