swift - AVFoundation 音频播放器仅在播放器停止时从滑块更新音量。我希望在拖动滑块时音量实时更新
问题描述
我正在构建的内容:一个应用程序,用户可以在其中以不同的音量播放不同的环境噪音。
问题:我希望在拖动滑块时音量自动改变。在其当前状态下,如果我停止播放器然后再次播放,它只会反映音量的变化。
问题示例:我点击一个声音来播放它(在这种情况下,是篝火的声音)。它开始正常播放。我将音量滑块拖动到不同的值以更改音量。这应该改变我听到的声音的音量,但音量没有变化。如果我点击声音将其关闭,然后再次点击将其重新打开,我只能听到新音量级别的声音。只有这样它才能反映新的音量水平。
我认为问题出在哪里:我相信问题出在函数 playCampFire() 内部。这是我在 do{} 语句中插入音量功能的地方。我认为是因为代码仅在执行 playCampFire() 函数时才执行,这仅在点击声音时发生。我尝试将 .volume 放在文件的不同部分,而不是仅仅将它放在 playCampFire() 函数中,但我没有运气。
这是我的代码:
import SwiftUI
import AVFoundation
var campFirePlayer: AVAudioPlayer!
var campFireIsTapped: Bool = false
struct CF_RowView: View {
@State var SFname: String
@State var nameOfSound: String
@State var urlOfSound: String
@State var slidervalue: Float
var body: some View {
HStack {
Image(systemName: SFname)
.frame(width: 20)
// Button to turn the sound on or off
Button(action: {
campFireIsTapped.toggle()
campFireIsTapped ? self.playCampFire() : self.stopCampFire()
}) {
Text(nameOfSound).frame(width: 150, alignment: .leading)
}
.padding(.leading, 10)
.foregroundColor(Color.primary)
Spacer()
Slider(value: $slidervalue)
.frame(width: 130, alignment: .trailing)
}.frame(width:320)
}
// function to play the sound
func playCampFire() {
let url = Bundle.main.url(forResource: urlOfSound, withExtension: "aif")
guard url != nil else {
return
}
do {
campFirePlayer = try AVAudioPlayer(contentsOf: url!)
campFirePlayer?.play()
campFirePlayer?.numberOfLoops = -1
campFirePlayer.volume = slidervalue
} catch {
print("\(error)")
}
}
// function to turn off the sound
func stopCampFire() {
let url = Bundle.main.url(forResource: urlOfSound, withExtension: "aif")
guard url != nil else {
return
}
do {
campFirePlayer = try AVAudioPlayer(contentsOf: url!)
campFirePlayer?.stop()
} catch {
print("\(error)")
}
}
}
这是预览的屏幕截图...
问题:我应该将 .volume 放在我的代码中的哪个位置,以便在我拖动音量滑块时它会自动更新,而无需停止声音并再次播放?
解决方案
我建议使用onChange来检测值何时更新。只需更新您的代码即可:
var body: some View {
HStack {
Image(systemName: SFname)
.frame(width: 20)
// Button to turn the sound on or off
Button(action: {
campFireIsTapped.toggle()
campFireIsTapped ? self.playCampFire() : self.stopCampFire()
}) {
Text(nameOfSound).frame(width: 150, alignment: .leading)
}
.padding(.leading, 10)
.foregroundColor(Color.primary)
Spacer()
Slider(value: $slidervalue)
.frame(width: 130, alignment: .trailing)
}
.frame(width:320)
.onChange(of: self.slidervalue) { value in
self.campFirePlayer.volume = value
}
}
推荐阅读
- node.js - npm WARN npm npm 不支持 Node.js
- react-native - 部分模拟“react-native”模块
- android - 通过 Java 中的 Android 应用程序以编程方式移动到 .csv 文件中的单元格内的新行
- python-3.x - 根据两列计算最大值
- r - 问题在R中折叠一个因子的水平
- python - 使用python快速实现dfs
- javascript - 如何从我的 Gatsby 网站创建独立的 JavaScript 包?
- .net-core - Flurl 与 Azure AD 身份验证
- java - 在 Spring Data JPA 中保存实体,其中包含另一个实体类型的列表
- node.js - 如何在服务器端导入fs