news 2026/4/15 20:18:19

Flutter for OpenHarmony 音乐播放器App实战25 - 歌词显示实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter for OpenHarmony 音乐播放器App实战25 - 歌词显示实现

前言

歌词显示是音乐播放器中非常受欢迎的功能,用户可以边听歌边看歌词,跟着一起唱。本篇我们来实现一个完整的歌词显示页面,包含歌词滚动列表、当前行高亮、点击跳转、以及底部播放控制。整个页面采用渐变背景设计,营造沉浸式的听歌体验。

功能分析

歌词页面需要实现以下功能:顶部显示歌曲名和歌手名,中间是可滚动的歌词列表,当前播放的歌词行高亮显示,用户可以点击任意歌词行跳转播放,底部提供进度条和播放控制按钮。

页面框架搭建

歌词页面需要管理当前播放行和滚动控制器,使用StatefulWidget实现:

classLyricsPageextendsStatefulWidget{constLyricsPage({super.key});@overrideState<LyricsPage>createState()=>_LyricsPageState();}class_LyricsPageStateextendsState<LyricsPage>{int currentLine=5;finalScrollController_scrollController=ScrollController();

currentLine记录当前播放到第几行歌词,默认值为5表示从第6行开始(索引从0开始)。_scrollController用于控制歌词列表的滚动位置,实现歌词自动滚动到当前行。

歌词数据结构

歌词数据使用List<Map>存储,每条歌词包含时间戳和文本内容:

finalList<Map<String,dynamic>>lyrics=[{'time':0,'text':'作词: 音乐人'},{'time':1,'text':'作曲: 音乐人'},{'time':5,'text':''},{'time':10,'text':'夜空中最亮的星'},{'time':15,'text':'能否听清'},{'time':20,'text':'那仰望的人'},{'time':25,'text':'心底的孤独和叹息'},{'time':30,'text':''},{'time':35,'text':'夜空中最亮的星'},{'time':40,'text':'能否记起'},{'time':45,'text':'曾与我同行'},{'time':50,'text':'消失在风里的身影'},{'time':55,'text':''},{'time':60,'text':'我祈祷拥有一颗透明的心灵'},{'time':65,'text':'和会流泪的眼睛'},{'time':70,'text':'给我再去相信的勇气'},{'time':75,'text':'越过谎言去拥抱你'},];

time字段表示这行歌词对应的播放时间(秒),text字段是歌词内容。空字符串表示歌词间的空行,用于视觉上的分隔。实际项目中这些数据通常从LRC文件解析而来。

页面主体结构

页面使用Stack叠加渐变背景和内容区域:

@overrideWidgetbuild(BuildContextcontext){returnScaffold(backgroundColor:Colors.black,body:Stack(children:[Container(decoration:BoxDecoration(gradient:LinearGradient(begin:Alignment.topCenter,end:Alignment.bottomCenter,colors:[constColor(0xFFE91E63).withOpacity(0.3),Colors.black]))),SafeArea(child:Column(children:[_buildHeader(),Expanded(child:_buildLyrics()),_buildControls(),],),),],),);}

Stack的第一层是渐变背景,从顶部的粉色渐变到底部的黑色。第二层是实际内容,使用Column布局分为三部分:顶部标题栏、中间歌词列表、底部播放控制。SafeArea确保内容不会被状态栏遮挡。

顶部标题栏

标题栏显示歌曲名、歌手名,以及返回和分享按钮:

Widget_buildHeader(){returnPadding(padding:constEdgeInsets.all(16),child:Row(children:[IconButton(icon:constIcon(Icons.keyboard_arrow_down,size:30),onPressed:()=>Get.back()),constExpanded(child:Column(children:[Text('夜空中最亮的星',style:TextStyle(fontSize:18,fontWeight:FontWeight.bold)),SizedBox(height:4),Text('逃跑计划',style:TextStyle(color:Colors.grey)),],),),IconButton(icon:constIcon(Icons.share),onPressed:(){}),],),);}

左侧是向下箭头按钮,点击返回上一页。中间使用Expanded占据剩余空间,显示歌曲名和歌手名,歌曲名使用粗体突出显示。右侧是分享按钮。这种布局是音乐App中常见的设计模式。

歌词列表实现

歌词列表是页面的核心部分,使用ListView.builder构建:

Widget_buildLyrics(){returnListView.builder(controller:_scrollController,padding:constEdgeInsets.symmetric(vertical:100),itemCount:lyrics.length,itemBuilder:(context,index){finalisCurrentLine=index==currentLine;returnGestureDetector(onTap:()=>setState(()=>currentLine=index),child:Container(padding:constEdgeInsets.symmetric(vertical:16,horizontal:32),child:Text(lyrics[index]['text'],textAlign:TextAlign.center,style:TextStyle(fontSize:isCurrentLine?20:16,fontWeight:isCurrentLine?FontWeight.bold:FontWeight.normal,color:isCurrentLine?constColor(0xFFE91E63):Colors.white.withOpacity(0.5),),),),);},);}

padding: const EdgeInsets.symmetric(vertical: 100)在列表顶部和底部添加100像素的空白,让歌词可以滚动到屏幕中央位置。

每行歌词用GestureDetector包裹,点击后更新currentLine实现跳转功能。当前行使用更大的字号(20px vs 16px)、粗体和粉色高亮显示,其他行使用半透明白色,形成明显的视觉对比。

底部播放控制

底部控制区包含进度条和播放按钮:

Widget_buildControls(){returnContainer(padding:constEdgeInsets.all(20),child:Column(children:[Row(children:[constText('2:35',style:TextStyle(color:Colors.grey,fontSize:12)),Expanded(child:Slider(value:0.4,activeColor:constColor(0xFFE91E63),inactiveColor:Colors.grey.withOpacity(0.3),onChanged:(v){})),constText('4:28',style:TextStyle(color:Colors.grey,fontSize:12)),],),

进度条使用Slider组件,左右两侧分别显示当前播放时间和总时长。activeColor设置已播放部分的颜色为粉色,inactiveColor设置未播放部分为灰色。

Row(mainAxisAlignment:MainAxisAlignment.spaceEvenly,children:[IconButton(icon:constIcon(Icons.shuffle),onPressed:(){}),IconButton(icon:constIcon(Icons.skip_previous,size:36),onPressed:(){}),Container(width:64,height:64,decoration:constBoxDecoration(color:Color(0xFFE91E63),shape:BoxShape.circle),child:IconButton(icon:constIcon(Icons.pause,size:32,color:Colors.white),onPressed:(){}),),IconButton(icon:constIcon(Icons.skip_next,size:36),onPressed:(){}),IconButton(icon:constIcon(Icons.repeat),onPressed:(){}),],),],),);}

播放控制按钮使用Row水平排列,spaceEvenly让按钮均匀分布。中间的播放/暂停按钮使用粉色圆形背景突出显示,是整个控制区的视觉焦点。上一首和下一首按钮使用较大的图标(36px),随机播放和循环播放按钮使用默认大小。

页面入口

歌词页面的入口在播放器页面,用户点击"点击查看歌词"文字即可进入:

GestureDetector(onTap:()=>Get.to(()=>constLyricsPage()),child:constText('点击查看歌词',style:TextStyle(color:Colors.white54))),

也可以在播放器页面的进度条区域添加这个入口,让用户更容易发现歌词功能。

扩展思路

实际项目中,歌词同步需要与播放器的播放进度联动。可以监听播放器的进度变化,根据当前播放时间找到对应的歌词行,然后更新currentLine并调用_scrollController.animateTo()平滑滚动到该行。

点击歌词跳转功能需要调用播放器的seek方法,将播放位置跳转到对应歌词的时间点。

还可以添加歌词翻译功能,在原歌词下方显示翻译文本,或者添加歌词字体大小调节、歌词背景模糊等个性化设置。

小结

本篇我们实现了一个功能完整的歌词显示页面,包含渐变背景、歌词列表、当前行高亮、点击跳转和播放控制。通过ListView.builder构建歌词列表,使用条件样式实现当前行高亮效果。渐变背景和统一的粉色主题色让页面视觉效果更加协调。在实际项目中,还需要与播放器进度联动,实现真正的歌词同步滚动功能。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/4 13:11:59

SQL 中的 WITH ... AS ...

SQL 中的 WITH ... AS ... 是一种非常强大且常用的语法结构&#xff0c;用于定义公用表表达式&#xff08;Common Table Expression&#xff0c;简称 CTE&#xff09;。它可以帮助你将复杂的查询拆解为更清晰、可读性更强的逻辑块。 一、基本语法 WITH cte_name AS (-- 子查询…

作者头像 李华
网站建设 2026/4/10 8:35:23

【程序员必学】GPT模型架构解析:预训练与微调技术详解(建议收藏)

本文详细解析了GPT模型的预训练与微调机制。预训练阶段通过自监督单向语言模型学习通用语义表示&#xff1b;微调阶段利用标注数据适配特定任务&#xff0c;但需解决灾难性遗忘问题。文章提出的混合损失函数方法&#xff0c;通过调节预训练与微调损失的权重平衡&#xff0c;有效…

作者头像 李华
网站建设 2026/4/14 23:08:12

探索AI提示工程国际化与本地化,提示工程架构师的独特视角

探索AI提示工程国际化与本地化:提示工程架构师的独特视角 一、引言:AI出海的“隐形门槛” 1.1 痛点引入:你可能遇到过的“翻译陷阱” 假设你是一家中国 SaaS 公司的产品经理,负责将AI客服系统推向东南亚市场。前期一切顺利:翻译了界面文案,适配了当地支付方式,甚至调…

作者头像 李华
网站建设 2026/4/11 3:31:50

农业供应链AI决策系统:架构师如何实现产销协同?

农业供应链AI决策系统&#xff1a;架构师如何用技术破解“产销错位”的千年难题&#xff1f; 一、开场&#xff1a;你见过凌晨3点的蔬菜批发市场吗&#xff1f; 去年冬天&#xff0c;我在山东寿光的蔬菜批发市场蹲了一周。凌晨2点&#xff0c;菜农王大爷的三轮车刚停稳&#xf…

作者头像 李华
网站建设 2026/4/15 15:46:36

Linux中get命令怎么用?

关于Linux&#xff0c;大家应该都知道它拥有许多的命令&#xff0c;这些命令可以帮助我们完成各种各样的操作。今天这篇文章主要跟大家聊聊get命令&#xff0c;那么Linux中get命令怎么用?以下是具体的内容介绍。get命令用于在Linux中获取和设置系统变量的值。它通过操纵底层的…

作者头像 李华
网站建设 2026/4/14 3:14:25

基于微信小程序的家校沟通管理系统的设计与实现

文章目录 详细视频演示项目介绍技术介绍功能介绍核心代码系统效果图源码获取 详细视频演示 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 基于微信小程序的家校沟通管理系统采用前后端分离架构&#xff0c;前端基于微信小程序开发&…

作者头像 李华