自学内容网 自学内容网

双非大学生自学鸿蒙5.0零基础入门到项目实战--黑马云音乐上篇

在这里插入图片描述
在这里插入图片描述

前言

今天开始正式做这个项目,项目1.0版本全程参考黑马云音乐制作,视频地址:黑马云音乐
真正实现从0到1的开发,我会将我遇到的问题来展示出来,环境:dev:5.0.5。感兴趣的同学可以和我一起进行从0到1的学习之路,计划两篇文章写完,预估用时4小时。废话不多说开肝

实践

1、修改软件基本信息

项目默认的APP中logo和名称都需要进行修改,以便确保项目的唯一性

操作

在这里插入图片描述

logo直接改就行了,名称需要跳转进去修改string文件

在这里插入图片描述

这里的logo也用我们APP的logo就行

在这里插入图片描述

测试

可以看到我们虚拟机中logo和昵称都变了

在这里插入图片描述

2、Navigation组件导航

概念

在这里插入图片描述

操作

将广告页和布局页创建出来,然后去实现首页的跳转功能

配置路由

在这里插入图片描述

这里面的参数大家不需要理解,知道他是页面跳转的路由即可,格式要保持统一
在这里插入图片描述

创建页面

index页

在这里插入图片描述

Start页

在这里插入图片描述

Layout页

在这里插入图片描述

测试

进入APP的时候会先进入广告页

在这里插入图片描述

点击按钮的时候会跳转到布局页

在这里插入图片描述

3、布局广告页

操作

这里的广告页其实就是一张图片,只需要我们全屏展示就行,这里有个注意事项,全屏展示一定要开放安全区,就是顶部和底部的区域

开放安全区代码:

.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])

开放安全区后的样式

在这里插入图片描述

未开放安全区的样式,可以看到上下都有空白区域

在这里插入图片描述

这是整体的代码解析,其实原理很简单,就是一个定时的页面跳转

在这里插入图片描述

广告页代码

@Builder
export function StartBuilder(){
  Start()
}

@Component
struct Start{
  pageStack:NavPathStack = new NavPathStack()
  aboutToAppear(): void { // 生命周期
    setTimeout(()=>{
      this.pageStack.replacePathByName("Layout",null,false) // 禁止回退到本页面
    },3000) // 3秒后自动跳转
  }

  build() {
    NavDestination(){
      // 广告
      Stack({alignContent:Alignment.TopEnd}){// 整体右上角排列
        Image($r('app.media.ad'))
          .width('100%')
          .height('100%')
          .expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
        Button('跳过')
          .backgroundColor(Color.Gray)
          .margin(15)
          .onClick(()=>{
            this.pageStack.replacePathByName("Layout",null,false) // 禁止回退到本页面
          })
      }
    }
    // .title('广告页')
    .onReady((context:NavDestinationContext)=>{
      this.pageStack = context.pathStack
    })
  }
}

4、Layout页

思路

在这里插入图片描述

这里因为涉及页面之间的切换,所以要用到Tabs组件,大致的语法如下:

在这里插入图片描述

操作

这里我讲一下核心逻辑
在这里插入图片描述
在这里插入图片描述

测试

可以看到下方tabs区域并不只是文字,还有对应的icon图标

在这里插入图片描述

可以对整体的主题进行修改,只需要添加背景色部分就行

在这里插入图片描述

代码

// Tabs接口
interface TabClass{
  text:string;
  icon:ResourceStr
}
@Builder
export function LayoutBuilder(){
  Layout()
}
@Component
struct Layout{
  pageStack:NavPathStack = new NavPathStack()
  tabData : TabClass[] = [
    {text:'推荐',icon:$r('app.media.ic_recommend')},
    {text:'发现',icon:$r('app.media.ic_find')},
    {text:'动态',icon:$r('app.media.ic_moment')},
    {text:'我的',icon:$r('app.media.ic_mine')},
  ]

  // tabs样式
  @Builder tabsBuilder(item:TabClass){
    Column({space:5}){
      Image(item.icon)
        .width(24)
        .fillColor('#63AAAA')
      Text(item.text)
        .fontSize(14)
        .fontColor('#63AAAA')
    }
  }

  build() {
    NavDestination(){
      Tabs({barPosition:BarPosition.End}){  // 组件位于最下方
        ForEach(this.tabData,(item:TabClass,index:number)=>{
          TabContent(){
            Text(item.text)
          }
          .tabBar(this.tabsBuilder(item))
        })
      }
    }
    .title('布局页')
    .onReady((context:NavDestinationContext)=>{
      this.pageStack = context.pathStack
    })
  }
}

Tabs交互功能

思路

简单的说就是根据索引来进行颜色和内容的改变,不同的索引对应不同的内容
在这里插入图片描述

操作

切换页码Tabs高亮显示

在这里插入图片描述

在这里插入图片描述

切换页码页面变化

这里先创建好这4个页面,内容简单点就行

在这里插入图片描述

在Layout页面根据索引来选择不同的页面进行渲染

在这里插入图片描述

测试

可以看到Tabs中的文字和页面文字对应上了,同时高亮效果页生效了
在这里插入图片描述

搜索区域

思路

在这里插入图片描述

设计

搜索框大致就是这样的形式

在这里插入图片描述

测试

在这里插入图片描述

代码

@Component
export struct Recommend {
  build() {
    Column(){
      //搜索区域
      Row(){
        Image($r('app.media.ic_search'))
          .width(22)
          .fillColor('#817D83')
        TextInput({placeholder:'输入歌曲名称'})
          .placeholderColor('#817D83')
          .padding({left:5})
          .fontColor('#999')
          .layoutWeight(1)
        Image($r('app.media.ic_code'))
          .width(20)
          .fillColor('#817D83')
      }
      .width('100%')
      .backgroundColor('#2D2B29')
      .border({radius:20})
      .padding({left:8,right:8})
    }
    .width('100%')
    .height('100%')
    .padding({left:10,right:10,top:5,bottom:5})
  }
}

轮播图区域

思路

先开启网络权限,因为图片要从网上获取并展示

在这里插入图片描述

操作

其实就是一个轮播图组件,这里的图片数据可以用本地的图片
在这里插入图片描述

测试

可以看到轮播图区域正常展示出来了
在这里插入图片描述

每日推荐区域

设计

每日推荐区域就是一个简单的横向列表组件

在这里插入图片描述
这里的每日推荐我们之前写过类似的函数,可以直接去套函数

在这里插入图片描述

测试

在这里插入图片描述

代码


// 每日推荐接口
interface recommendDailyType {
  img: string  // 图片
  title: string  // 简介文字
  type:string  // 标题文字
  top:string  // 标题背景色
  bottom: string  // 简介背景色
}
  // 每日推荐数据
  dailyRecommend: recommendDailyType[] = [
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend1.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '每日推荐',
      top: '#660000',
      bottom: '#382e2f'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend2.png',
      title: '从 [Nothing on Me] 开启无限漫游',
      type: '私人漫游',
      top: '#382e2f',
      bottom: '#a37862'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend3.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '华语流行',
      top: '#a37862',
      bottom: '#174847'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend4.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '私人雷达',
      top: '#174847',
      bottom: '#174847'
    }
  ]

  @Builder
  titleBuilder (title: string) {
    Row() {
      Text(title)
        .fontColor('#fff')
        .fontWeight(700)
        .layoutWeight(1)
      Image($r('app.media.ic_more'))
        .width(22)
        .fillColor('#fff')
    }
    .width('100%')
    .height(40)
  }
      // 每日推荐区域
      this.titleBuilder("每日推荐")
      List(){
        ForEach(this.dailyRecommend,(item:recommendDailyType)=>{
          ListItem(){
            Column(){
              Text(item.type)
                .width('100%')
                .height(40)
                .backgroundColor(item.top)
                .padding({left:5})
                .fontSize(14)
                .fontColor('#fff')
              Image(item.img)
                .width('100%')
              Text(item.title)
                .width('100%')
                .backgroundColor(item.bottom)
                .padding(5)
                .fontSize(14)
                .fontColor('#fff')
                .maxLines(2)
                .textOverflow({overflow:TextOverflow.Ellipsis}) // 文本超过2行自动省略
            }
            .width("40%")
            .border({radius:10})
            .margin({right:10})
            .clip(true) // 会根据父组件对子组件进行裁剪
          }
        })
      }
      .listDirection(Axis.Horizontal) //横向排布

推荐歌单区域

设计

不难发现整体还是List,内部一个Column,上面是Stack,下面是Text
在这里插入图片描述
在这里插入图片描述

测试

在这里插入图片描述

参考文档

视频参考:黑马云音乐
所有素材来源:

黑马云音乐图片素材地址
黑马云音乐变量素材

总结

我这里的推荐页做了一个小改变,就是可以进行滑动,如果内容多的话需要进行滑动,今天就先完成推荐页面的开发,剩下的页面晚上有时间的话在开始肝吧,所有的素材都可以找到,希望大家可以认真的观看,整体并不难,主要是格式的调整

推荐页全套代码

// 每日推荐接口
interface recommendDailyType {
  img: string  // 图片
  title: string  // 简介文字
  type:string  // 标题文字
  top:string  // 标题背景色
  bottom: string  // 简介背景色
}
// 推荐歌单接口
interface recommendListType {
  img: string
  title: string
  count:string
}



@Component
export struct Recommend {
  // 轮播图数据
  swiperList : string[] = [
    "http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner1.png",
    "http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner2.png",
    "http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner3.png",
    "http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner4.png",
    "http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/banner5.png",
  ]

  // 每日推荐数据
  dailyRecommend: recommendDailyType[] = [
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend1.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '每日推荐',
      top: '#660000',
      bottom: '#382e2f'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend2.png',
      title: '从 [Nothing on Me] 开启无限漫游',
      type: '私人漫游',
      top: '#382e2f',
      bottom: '#a37862'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend3.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '华语流行',
      top: '#a37862',
      bottom: '#174847'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/recommend4.png',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      type: '私人雷达',
      top: '#174847',
      bottom: '#174847'
    }
  ]
  // 推荐歌单数据
  recommendList: recommendListType[] = [
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/list1.jpg',
      title: '每日推荐 | 今天从《不得不爱》听起 | 私人雷达',
      count: '270.9万'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/list2.jpg',
      title: 'Yasuo和更多好听的 | 华语私人雷达 | 回忆8090',
      count: '476.1万'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/list3.jpg',
      title: 'Trap Remix丨当欧美热单遇上毒性低音',
      count: '186.3万'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/list4.jpg',
      title: '满级人类进化之路必备BGM | 根本停不下来',
      count: '186.3万'
    },
    {
      img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/list5.jpg',
      title: '认真去聆听这个世界的每一分每一秒 (强烈推荐)',
      count: '362.8万'
    }
  ]

  @Builder
  titleBuilder (title: string) {
    Row() {
      Text(title)
        .fontColor('#fff')
        .fontWeight(700)
        .layoutWeight(1)
      Image($r('app.media.ic_more'))
        .width(22)
        .fillColor('#fff')
    }
    .width('100%')
    .height(40)
  }


  build() {
    Column(){
      //搜索区域
      Row(){
        Image($r('app.media.ic_search'))
          .width(22)
          .fillColor('#817D83')
        TextInput({placeholder:'输入歌曲名称'})
          .placeholderColor('#817D83')
          .padding({left:5})
          .fontColor('#999')
          .layoutWeight(1)
        Image($r('app.media.ic_code'))
          .width(20)
          .fillColor('#817D83')
      }
      .width('100%')
      .backgroundColor('#2D2B29')
      .border({radius:20})
      .padding({left:8,right:8})
      .margin({bottom:10})
      Scroll(){
        Column({space:10}){
          // 轮播图区域
          Swiper(){
            ForEach(this.swiperList,(item:string)=>{
              Image(item)
                .width('100%')
                .border({radius:10})
            })
          }
          .autoPlay(true)
          // 每日推荐区域
          this.titleBuilder("每日推荐")
          List(){
            ForEach(this.dailyRecommend,(item:recommendDailyType)=>{
              ListItem(){
                Column(){
                  Text(item.type)
                    .width('100%')
                    .height(40)
                    .backgroundColor(item.top)
                    .padding({left:5})
                    .fontSize(14)
                    .fontColor('#fff')
                  Image(item.img)
                    .width('100%')
                  Text(item.title)
                    .width('100%')
                    .backgroundColor(item.bottom)
                    .padding(5)
                    .fontSize(14)
                    .fontColor('#fff')
                    .maxLines(2)
                    .textOverflow({overflow:TextOverflow.Ellipsis}) // 文本超过2行自动省略
                }
                .width("40%")
                .border({radius:10})
                .margin({right:10})
                .clip(true) // 会根据父组件对子组件进行裁剪
              }
            })
          }
          .listDirection(Axis.Horizontal) //横向排布
          .height(230)
          .scrollBar(BarState.Off)
          // 推荐歌单
          this.titleBuilder('推荐歌单')
          List(){
            ForEach(this.recommendList,(item:recommendListType)=>{
              ListItem(){
                Column(){
                  Stack({alignContent:Alignment.TopStart}){
                    Image(item.img)
                      .width('100%')
                      .height(100)
                      .border({radius:8})
                    Text(item.count)
                      .fontColor('#fff')
                      .fontSize(12)
                      .fontWeight(700)
                      .margin(5)
                  }
                  Text(item.title)
                    .width('100%')
                    .fontColor('#fff')
                    .fontSize(14)
                    .padding(5)
                    .maxLines(2)
                    .textOverflow({overflow:TextOverflow.Ellipsis}) // 文本超过2行自动省略
                }
                .width('30%')
                .margin({right:10})
              }
            })
          }
          .listDirection(Axis.Horizontal) //横向排布
          .scrollBar(BarState.Off)
          .height(200)
        }
        .width('100%')
        .padding({left:10,right:10,top:5,bottom:5})
      }
    }
    .width('100%')
    .height('100%')
  }
}

原文地址:https://blog.csdn.net/2302_80329073/article/details/154392976

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!