我必须在iPad上更改音量并使用以下代码:
[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];
但这会改变音量并在iPad上显示系统音量条。 如何在不显示音量条的情况下更改声音?
我知道,setVolume:
已被弃用,并且每个人都说要使用MPVolumeView
。如果这是解决问题的唯一方法,那么如何使用MPVolumeView
更改音量?我没有在MPVolumeView
中看到任何改变声音的方法。
我应该和MPVolumeView
一起使用另一个班级吗?
但最好使用MPMusicPlayerController
。
感谢您的建议!
答案 0 :(得分:38)
您需要在延迟一段时间后更改slider.value
。
extension MPVolumeView {
static func setVolume(_ volume: Float) {
let volumeView = MPVolumeView()
let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
slider?.value = volume
}
}
}
用法:
MPVolumeView.setVolume(0.5)
答案 1 :(得分:16)
MPVolumeView
有一个滑块,通过更改滑块的值,您可以更改设备音量。我写了一个MPVolumeView
扩展名来轻松访问滑块:
extension MPVolumeView {
var volumeSlider:UISlider {
self.showsRouteButton = false
self.showsVolumeSlider = false
self.hidden = true
var slider = UISlider()
for subview in self.subviews {
if subview.isKindOfClass(UISlider){
slider = subview as! UISlider
slider.continuous = false
(subview as! UISlider).value = AVAudioSession.sharedInstance().outputVolume
return slider
}
}
return slider
}
}
答案 2 :(得分:4)
我不认为有任何方法可以在不闪烁音量控制的情况下改变音量。你应该像这样使用MPVolumeView
:
MPVolumeView* volumeView = [[MPVolumeView alloc] init];
// Get the Volume Slider
UISlider* volumeViewSlider = nil;
for (UIView *view in [volumeView subviews]){
if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
volumeViewSlider = (UISlider*)view;
break;
}
}
// Fake the volume setting
[volumeViewSlider setValue:1.0f animated:YES];
[volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
答案 3 :(得分:3)
@udjat在 Swift 3
中的回答extension MPVolumeView {
var volumeSlider: UISlider? {
showsRouteButton = false
showsVolumeSlider = false
isHidden = true
for subview in subviews where subview is UISlider {
let slider = subview as! UISlider
slider.isContinuous = false
slider.value = AVAudioSession.sharedInstance().outputVolume
return slider
}
return nil
}
}
答案 4 :(得分:3)
extension UIViewController {
func setVolumeStealthily(_ volume: Float) {
guard let view = viewIfLoaded else {
assertionFailure("The view must be loaded to set the volume with no UI")
return
}
let volumeView = MPVolumeView(frame: .zero)
guard let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider else {
assertionFailure("Unable to find the slider")
return
}
volumeView.clipsToBounds = true
view.addSubview(volumeView)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak slider, weak volumeView] in
slider?.setValue(volume, animated: false)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak volumeView] in
volumeView?.removeFromSuperview()
}
}
}
}
用法:
// set volume to 50%
viewController.setVolume(0.5)
答案 5 :(得分:2)
这是Swift的解决方案。它可能是一个阴暗的,所以如果Apple在我发布时批准了这个,我会告诉你。同时,这对我来说很合适:
在View Controller中定义MPVolumeView和可选的UISlider
private let volumeView: MPVolumeView = MPVolumeView()
private var volumeSlider: UISlider?
在故事板中,定义一个隐藏在用户身上的视图(height = 0应该可以做到这一点),然后为它设置一个出口(我们称之为 hiddenView 这里)。如果您不希望在更改音量时显示音量HUD,请执行此步骤(请参阅下面的注释):
@IBOutlet weak var hiddenView: UIView!
在viewDidLoad()或运行一次的某个init-y中,将实际控制卷的UISlider从步骤(1)中捕获到可选的UISlider中:
override func viewDidLoad() {
super.viewDidLoad()
...
hiddenView.addSubview(volumeView)
for view in volumeView.subviews {
if let vs = view as? UISlider {
volumeSlider = vs
break
}
}
}
如果要在代码中设置音量,只需将volumeSlider?.value设置为0.0到1.0之间的任意值,例如:增加音量:
func someFunc() {
if volumeSlider?.value < 0.99 {
volumeSlider?.value += 0.01
} else {
volumeSlider?.value = 1.0
}
}
重要提示: 当您更改代码中的音量或用户单击外部音量按钮时,此解决方案将阻止iPhone的音量HUD出现。如果您确实要显示HUD,请跳过所有隐藏的视图内容,并且根本不要将MPVolumeView添加为子视图。这将导致iOS在音量改变时显示HUD。
答案 6 :(得分:2)
版本:Swift 3&amp; Xcode 8.1
extension MPVolumeView {
var volumeSlider:UISlider { // hacking for changing volume by programing
var slider = UISlider()
for subview in self.subviews {
if subview is UISlider {
slider = subview as! UISlider
slider.isContinuous = false
(subview as! UISlider).value = AVAudioSession.sharedInstance().outputVolume
return slider
}
}
return slider
}
}
答案 7 :(得分:1)
Swift&gt; 2.2,iOS&gt; 8.0,
我没有找到任何我正在寻找的解决方案,但我最终将其作为解决方案:
let volumeView = MPVolumeView()
override func viewDidLoad() {
...
view.addSubview(volumeView)
volumeView.alpha = 0.00001
}
func changeSpeakerSliderPanelControls(volume: Float) {
for subview in self.volumeView.subviews {
if subview.description.rangeOfString("MPVolumeSlider") != nil {
let slider = subview as! UISlider
slider.value = volume
break
}
}
}
答案 8 :(得分:1)
这是我的音频播放器应用的音量控制:
import UIKit
import MediaPlayer
class UIVolumeSlider: UISlider {
func activate(){
updatePositionForSystemVolume()
guard let view = superview else { return }
let volumeView = MPVolumeView(frame: .zero)
volumeView.alpha = 0.000001
view.addSubview(volumeView)
try? AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
AVAudioSession.sharedInstance().addObserver(self, forKeyPath: "outputVolume", options: .new, context: nil)
addTarget(self, action: #selector(valueChanged), for: .valueChanged)
}
func deactivate(){
AVAudioSession.sharedInstance().removeObserver(self, forKeyPath: "outputVolume")
removeTarget(self, action: nil, for: .valueChanged)
superview?.subviews.first(where: {$0 is MPVolumeView})?.removeFromSuperview()
}
func updatePositionForSystemVolume(){
try? AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
value = AVAudioSession.sharedInstance().outputVolume
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume", let newVal = change?[.newKey] as? Float {
setValue(newVal, animated: true)
}
}
@objc private func valueChanged(){
guard let superview = superview else {return}
guard let volumeView = superview.subviews.first(where: {$0 is MPVolumeView}) as? MPVolumeView else { return }
guard let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider else { return }
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
slider.value = self.value
}
}
}
如何连接:
@IBOutlet private var volumeSlider:UIVolumeSlider!
volumeSlider.updatePositionForSystemVolume()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
volumeSlider.activate()
}
override func viewWillDisappear(_ animated: Bool) {
volumeSlider.deactivate()
super.viewWillDisappear(animated)
}
答案 9 :(得分:0)
您可以将默认UISlider与此代码一起使用:
import MediaPlayer
class CusomViewCOntroller: UIViewController
// could be IBOutlet
var customSlider = UISlider()
// in code
var systemSlider = UISlider()
override func viewDidLoad() {
super.viewDidLoad()
let volumeView = MPVolumeView()
if let view = volumeView.subviews.first as? UISlider{
systemSlider = view
}
}
接下来在代码中写一下
systemSlider.value = customSlide.value
答案 10 :(得分:0)
快捷键4:
var player: AVPlayer!
...
player.volume = 0.5 // 50% level
答案 11 :(得分:0)
Swift 5 / iOS 13
这是我发现的访问系统音量级别的最可靠方法。这是基于此处的其他答案,但不浪费能量,也不需要异步等待。
在初始化期间(例如在viewDidLoad
中),创建屏幕外的MPVolumeView
:
var hiddenSystemVolumeSlider: UISlider!
override func viewDidLoad() {
let volumeView = MPVolumeView(frame: CGRect(x: -CGFloat.greatestFiniteMagnitude, y:0, width:0, height:0))
view.addSubview(volumeView)
hiddenSystemVolumeSlider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
}
然后在需要时使用隐藏的滑块获取或设置系统音量:
var systemVolume:Float {
get {
return hiddenSystemVolumeSlider.value
}
set {
hiddenSystemVolumeSlider.value = newValue
}
}