[HarmonyOS NEXT 实战案例:音乐播放器] 基础篇 - 水平分割布局打造音乐播放器界面

2025-06-09 23:13:05
101次阅读
0个评论

[HarmonyOS NEXT 实战案例:音乐播放器] 基础篇 - 水平分割布局打造音乐播放器界面

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

image.png

引言

在移动应用开发中,音乐播放器是一个经典的应用场景。一个好的音乐播放器界面不仅需要美观,还需要功能区域划分清晰,操作便捷。本教程将详细讲解如何使用HarmonyOS NEXT的RowSplit组件构建一个音乐播放器界面,通过水平分割布局将界面分为专辑封面区域和播放控制区域。

组件概述

在本案例中,我们将使用以下HarmonyOS NEXT组件:

组件名称 功能描述
RowSplit 水平分割布局容器,将界面分为上下两部分
Column 垂直布局容器,用于垂直排列子组件
Row 水平布局容器,用于水平排列子组件
Image 图片组件,用于显示专辑封面
Text 文本组件,用于显示歌曲名称、歌手和时间
Button 按钮组件,用于播放控制和其他操作
Slider 滑块组件,用于进度条和音量控制

代码实现

组件结构

首先,我们定义了一个名为MusicPlayerExample的自定义组件:

@Component
export struct MusicPlayerExample {
    @State isPlaying: boolean = false
    @State currentTime: number = 0
    @State totalTime: number = 240 // 4分钟

    build() {
        // 组件内容
    }
}

在这个组件中,我们定义了三个状态变量:

  • isPlaying:表示当前是否正在播放音乐
  • currentTime:表示当前播放时间(秒)
  • totalTime:表示音乐总时长(秒)

外层容器

我们使用Column组件作为最外层容器,包含标题文本和主要内容区域:

Column() {
    Text('音乐播放器布局')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })

    RowSplit() {
        // RowSplit内容
    }
    .height(400)
}
.padding(15)

外层Column设置了15的内边距,确保整个界面与屏幕边缘有适当的间距。

水平分割布局

我们使用RowSplit组件将界面分为上下两部分:

RowSplit() {
    // 专辑封面区域
    Column() {
        // 专辑封面区域内容
    }
    .height('60%')
    .justifyContent(FlexAlign.Center)
    .backgroundColor('#f8f9fa')

    // 播放控制区域
    Column() {
        // 播放控制区域内容
    }
    .padding(10)
}
.height(400)

在这个RowSplit中:

  1. 上部区域是专辑封面区域,占总高度的60%,背景色为浅灰色,内容居中对齐
  2. 下部区域是播放控制区域,设置了10的内边距
  3. 整个RowSplit的高度设置为400像素

专辑封面区域

专辑封面区域包含专辑图片、歌曲名称、歌手名称以及喜欢和分享按钮:

Column() {
    Image($r('app.media.big29'))
        .width(200)
        .height(200)
        .borderRadius(10)
        .margin({ top: 20 })
    Text('夏日记忆')
        .fontSize(18)
        .margin({ top: 10 })
    Text('林小夏')
        .fontSize(16)
        .margin({ top: 5 })
        .fontColor('#666')

    // 喜欢和分享按钮
    Row() {
        Button($r('app.media.01'))
            .width(24)
            .height(24)
            .backgroundColor(Color.Transparent)
        Button($r('app.media.02'))
            .width(24)
            .height(24)
            .backgroundColor(Color.Transparent)
            .margin({ left: 20 })
    }
    .margin({ top: 15 })
}
.height('60%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#f8f9fa')

在这个区域中:

  1. 专辑封面图片宽高均为200像素,设置了10像素的圆角和20像素的上边距
  2. 歌曲名称使用18像素的字体大小,设置了10像素的上边距
  3. 歌手名称使用16像素的字体大小,设置了5像素的上边距,字体颜色为灰色
  4. 喜欢和分享按钮使用Row组件水平排列,每个按钮宽高均为24像素,背景色透明

播放控制区域

播放控制区域包含进度条、播放控制按钮和音量控制:

Column() {
    // 进度条
    Row() {
        Text(this.formatTime(this.currentTime))
            .fontSize(14)
            .width(50)
        Slider({
            value: this.currentTime,
            min: 0,
            max: this.totalTime,
            style: SliderStyle.OutSet
        })
            .onChange((value: number) => {
                this.currentTime = value
            })
            .width('70%')
        Text(this.formatTime(this.totalTime))
            .fontSize(14)
            .width(50)
    }
    .width('90%')
    .margin({ top: 20, bottom: 10 })

    // 播放控制按钮
    Row() {
        Button($r('app.media.03'))
            .width(32)
            .height(32)
            .backgroundColor(Color.Transparent)
        Button(this.isPlaying ? $r('app.media.04') : $r('app.media.05'))
            .width(40)
            .height(40)
            .backgroundColor(Color.Transparent)
            .margin({ left: 20, right: 20 })
            .onClick(() => {
                this.isPlaying = !this.isPlaying
            })
        Button($r('app.media.01'))
            .width(32)
            .height(32)
            .backgroundColor(Color.Transparent)
    }
    .margin({ top: 10 })

    // 音量和其他控制
    Row() {
        Button($r('app.media.02'))
            .width(24)
            .height(24)
            .backgroundColor(Color.Transparent)
        Slider({
            value: 80,
            min: 0,
            max: 100,
            style: SliderStyle.OutSet
        })
            .width(100)
            .margin({ left: 10 })
        Button($r('app.media.03'))
            .width(24)
            .height(24)
            .backgroundColor(Color.Transparent)
            .margin({ left: 15 })
    }
    .margin({ top: 20 })
}
.padding(10)

在这个区域中:

  1. 进度条区域包含当前时间文本、进度滑块和总时间文本,宽度为父容器的90%
  2. 播放控制按钮区域包含上一曲、播放/暂停和下一曲按钮,播放/暂停按钮根据isPlaying状态显示不同的图标
  3. 音量控制区域包含音量图标、音量滑块和其他控制按钮

时间格式化函数

为了将秒数转换为分:秒格式,我们定义了一个formatTime方法:

private formatTime(seconds: number): string {
    const mins = Math.floor(seconds / 60)
    const secs = Math.floor(seconds % 60)
    return `${mins}:${secs < 10 ? '0' + secs : secs}`
}

这个方法将秒数转换为分:秒格式,并确保秒数小于10时前面补0。

布局分析

水平分割的应用

在本案例中,我们使用RowSplit组件将界面分为上下两部分:

  1. 上部区域(专辑封面区域)

    • 占总高度的60%
    • 包含专辑封面、歌曲信息和操作按钮
    • 内容居中对齐,背景色为浅灰色
  2. 下部区域(播放控制区域)

    • 占总高度的40%(隐式设置)
    • 包含进度条、播放控制按钮和音量控制
    • 设置了内边距,确保内容与边缘有适当的间距

这种水平分割的布局方式非常适合音乐播放器界面,使得用户可以清晰地看到专辑封面和歌曲信息,同时方便地操作播放控制。

状态管理

在本案例中,我们使用@State装饰器定义了三个状态变量:

  1. isPlaying:控制播放/暂停按钮的图标显示
  2. currentTime:控制进度条的当前值和当前时间文本的显示
  3. totalTime:控制进度条的最大值和总时间文本的显示

当用户点击播放/暂停按钮时,isPlaying状态会切换,从而改变按钮的图标。当用户拖动进度条时,currentTime状态会更新,从而改变当前时间文本的显示。

布局技巧

比例设置

在本案例中,我们使用百分比来设置专辑封面区域的高度(height('60%')),这样可以确保在不同屏幕尺寸下,专辑封面区域和播放控制区域的比例保持一致。

内容居中

我们使用justifyContent(FlexAlign.Center)属性将专辑封面区域的内容垂直居中对齐,这样可以确保在不同屏幕尺寸下,专辑封面始终位于区域的中央。

边距设置

我们为各个组件设置了适当的边距,确保界面布局美观:

  1. 外层Column设置了15的内边距,确保整个界面与屏幕边缘有适当的间距
  2. 专辑封面设置了20的上边距,确保与顶部有适当的间距
  3. 歌曲名称和歌手名称分别设置了10和5的上边距,确保文本之间有适当的间距
  4. 播放控制区域的各个部分也设置了适当的边距,确保各个控件之间有适当的间距

总结

在本教程中,我们学习了如何使用HarmonyOS NEXT的RowSplit组件构建一个音乐播放器界面。通过水平分割布局,我们将界面分为专辑封面区域和播放控制区域,使得界面结构清晰,功能区域划分明确。

我们还学习了如何使用@State装饰器管理组件状态,如何使用Slider组件实现进度条和音量控制,以及如何使用onClick事件处理用户交互。

收藏00

登录 后评论。没有帐号? 注册 一个。