音乐播放器自动滚动歌词组UI件
以下内容由 AI 翻译,如有问题请 点此提交 issue 反馈
介绍
lyric-view-cj 是一个可关联音乐播放器的自定义歌词组件。
特性
- 从文件解析双语歌词
- 从文本解析双语歌词
- 设置拖动歌词时选中歌词的字体颜色
- 设置拖动歌词时左侧时间字体颜色
- 设置歌词为空时屏幕中央显示的文字,如“暂无歌词”
- 支持自定义样式
源码目录
├─ AppScope
├─ doc # API文档和使用手册存放目录
├─ entry # 示例代码文件夹
├─ hvigor # 构建工具目录
├─ lyricview # lyricview 库源目录
│ └─ src
│ └─ main
│ ├─ cangjie # lyricview 源码
│ └─ resources # 资源文件
└─ README.md # lyric-view-cj 介绍及使用说明
接口说明
主要类和函数接口说明详见 API
使用说明
- 通过 module 引入
- 克隆下载项目
- 将 lyricview 模块拷贝到应用项目下
- 修改 entry 下的 cjpm.toml 文件,在此文件中添加 lyricview 依赖,如下:
[dependencies] [dependencies.lyricview] path = "../lyricview" - 在项目中引用 lyricview 项目
import lyricview.*
- 把 lyricview 作为三方库依赖引入
- 目标工程把 lyricview 依赖库作为 git submodule 引入
> cd $工程根目录 > mkdir third-party > cd third-party > git submodule add "https://gitcode.com/Cangjie-TPC/lyric-view-cj" - 修改 entry 下的 cjpm.toml 文件,在此文件中添加 lyricview 依赖,如下:
[dependencies] [dependencies.lyricview] path = "../lyricview" - 在项目中使用 lyricview 组件
import lyricview.*
- 目标工程把 lyricview 依赖库作为 git submodule 引入
功能示例
import ohos.state_macro_manage.*
import ohos.component.*
import std.collection.ArrayList
import ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.hilog.Hilog
import lyricview.bean.*
import lyricview.extensions.*
import lyricview.parse.*
import lyricview.view.*
import std.sync.*
import std.math.*
@Entry
@Component
class LyricViewTestCase {
@State
var mediaPosition: Int64 = 0
var lyric: Option<Lyric> = None
@State
var lyricController: LyricController = LyricController()
var testIndex = 0
var testTimer = -1
var emptyDuration: Int64 = 60 * 1000
var parser: LyricParser = LyricParser()
@State
var title: String = ""
@State
var isV2: Bool = true
var i = 0
var j = 0
private var timerInstance: ?Timer = None
protected func aboutToAppear():Unit {
this.lyricController
.setTextSize(18.0)
.setCacheSize(4)
.setTextColor(Color(0x7cffffff))
.setHighlightColor(Color(0xffffffff))
.setLineSpace(18.0)
.setHighlightScale(1.3)
.setHighlightBold(true)
.setHighlightBold(false)
.setEmptyHint("当前没有歌词")
.setAlignMode(AlignMode.Center)
}
public func cbFn(mediaPositionT: Int64): Unit {
this.mediaPosition = mediaPositionT
}
func build() {
Column() {
Text(this.title).margin(16).fontColor(Color(0xffffff)).fontSize(24).fontColor(Color(0x80ffffff))
Row() {
LyricView(
controller: this.lyricController,
enableSeek: true,
seekUIColor: Color(0xffd4d4d4),
seekLineColor: Color(0xffffffff),
seekUIStyle: "listItem",
onSeekAction: {
position =>
this.mediaPosition = position
return true
}
)
}.width(100.percent).layoutWeight(1)
Column() {
Row() {
Text('centerMode').fontColor(Color(0xffffff)).fontSize(16).padding(4)
Toggle(ToggleType.SwitchType, isOn: true).onChange(
{
isOn => if (isOn) {
this.lyricController.setAlignMode(AlignMode.Center)
} else {
this.lyricController.setAlignMode(AlignMode.Left)
}
})
}
Row() {
Button('play')
.fontSize(16)
.margin(left: 16)
.onClick(
{
=>
this.testIndex++
this.lyric = this.parser.parse(testLrcArray)
if (let Some(currentLyric) <- this.lyric) {
this.title = currentLyric.getTitle()
this.lyricController.setLyric(currentLyric)
}
if (let Some(timerInstance) <- this.timerInstance) {
timerInstance.cancel()
}
this.mediaPosition = 0
this.timerInstance = this.lyricController.lyricsScrolling(cbFn)
}
)
Button('color')
.fontSize(16)
.margin(left: 16)
.onClick(
{
=>
this.i++
if (this.i % 2 == 0) {
this
.lyricController
.setTextColor(Color(0x80ffffff))
.setHighlightColor(Color(0xffffffff))
} else {
this
.lyricController
.setTextColor(Color(0x80e3d052))
.setHighlightColor(Color(0xe3d052))
}
}
)
Button('size')
.fontSize(16)
.margin(left: 16)
.onClick(
{
=>
this.j++
if (this.j % 2 == 0) {
this.lyricController.setTextSize(12.0).setLineSpace(12.0)
} else {
this.lyricController.setTextSize(18.0).setLineSpace(18.0)
}
}
)
Button('clear')
.fontSize(16)
.margin(left: 16)
.onClick(
{
=>
let lyric: Option<Lyric> = None
this.lyricController.setLyric(lyric)
}
)
}.width(100.percent).justifyContent(FlexAlign.SpaceBetween).margin(top: 16)
}.width(100.percent).justifyContent(FlexAlign.Center).margin(top: 36)
Slider(
style: SliderStyle.InSet,
max: if (let Some(lyric) <- this.lyric) {
Float64(lyric.getLyricList()[lyric.getLyricList().size - 1].getBeginTime())
} else {
Float64(this.emptyDuration)
},
value: Float64(this.mediaPosition)
)
.blockColor(Color(0xfffafafa))
.trackColor(Color(0xffffff))
.width(100.percent)
.onChange(
{
value: Float64, mode: SliderChangeMode => if (getSliderChangeMode(mode) || getMode(mode) == 3) {
this.mediaPosition = Int64(value)
this.lyricController.updatePosition(this.mediaPosition)
}
})
Text(Int64(round(Float64(this.mediaPosition / 1000))).toString() + "s")
.fontColor(Color(0xffffff))
.fontSize(18)
.margin(top: 16)
}.linearGradient(
angle: 360.0,
colors: [(Color(0xff2e3030), 0.0), (Color(0x662e3030), 1.0)]
)
.padding(16)
.width(100.percent)
.height(100.percent)
.justifyContent(FlexAlign.Center)
}
public func getSliderChangeMode(that: SliderChangeMode): Bool {
match (that) {
case SliderChangeMode.End => true
case _ => false
}
}
public func getMode(that: SliderChangeMode): Int64 {
match (that) {
case SliderChangeMode.Begin => 1
case SliderChangeMode.Moving => 2
case SliderChangeMode.End => 3
case _ => 4
}
}
}
约束与限制
已在以下版本中验证通过:
DevEco Studio 5.1.1 Release(5.1.1.851) 需使用支持19及以上版本的SdkVersion
开源协议
本项目基于 Apache License 许可,欢迎您享受并参与开源。
参与贡献
欢迎提交 PR、Issue 或通过任何形式参与贡献。