iOS 9:如何以编程方式更改音量而不显示系统声音栏弹出窗口?
我必须更改iPad上的音量,并使用以下代码:iOS 9:如何以编程方式更改音量而不显示系统声音栏弹出窗口?,ios,objective-c,ios9,mpmusicplayercontroller,mpvolumeview,Ios,Objective C,Ios9,Mpmusicplayercontroller,Mpvolumeview,我必须更改iPad上的音量,并使用以下代码: [[MPMusicPlayerController applicationMusicPlayer] setVolume:0]; import MediaPlayer class CusomViewCOntroller: UIViewController // could be IBOutlet var customSlider = UISlider() // in code var system
[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];
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
}
}
但这会改变音量,并在iPad上显示系统音量栏如何在不显示音量栏的情况下更改声音?
我知道,setVolume:
已被弃用,每个人都说要使用MPVolumeView
。如果这是解决问题的唯一方法,那么如何使用MPVolumeView
更改音量?我在MPVolumeView
中没有看到任何改变声音的方法我是否应该与
MPVolumeView
一起使用另一个类
但最好使用MPMusicLayerController
谢谢你的建议 我认为如果不闪烁音量控制,就没有办法改变音量。您应该像这样使用
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];
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
}
}
Swift>2.2,iOS>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
}
}
}
在Swift中有一个解决方案。这可能是一个阴暗的问题,所以当我发布时,我会让你知道苹果是否批准了这一点。同时,这对我来说很好:
private let volumeView: MPVolumeView = MPVolumeView()
private var volumeSlider: UISlider?
func someFunc() {
if volumeSlider?.value < 0.99 {
volumeSlider?.value += 0.01
} else {
volumeSlider?.value = 1.0
}
}
func someFunc(){
如果体积滑块?值<0.99{
体积滑块?.value+=0.01
}否则{
体积滑块?.value=1.0
}
}
此解决方案将防止iPhone的音量HUD出现——无论是在代码中更改音量时,还是在用户单击外部音量按钮时。如果确实要显示HUD,则跳过所有隐藏的视图内容,并且根本不将MPVolumeView添加为子视图。这将导致iOS在音量变化时显示HUD。版本:Swift 3&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
}
}
@乌德贾特在《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
}
}
用法:
// set volume to 50%
viewController.setVolume(0.5)
MPVolumeView.setVolume(0.5)
您可以将默认UISlider与以下代码一起使用:
[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];
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
2018年,致力于iOS 11.4 您需要在一个小延迟后更改
滑块.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
}
}
}
用法:
// set volume to 50%
viewController.setVolume(0.5)
MPVolumeView.setVolume(0.5)
这是我的音频播放器应用程序的音量控制:
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
}
}
}
如何连接:
Swift 5/iOS 13
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
}
}
以下是我找到的访问系统卷级别的最可靠的方法。这是基于这里的其他答案,但不浪费能源,也不需要异步等待
在初始化期间(例如在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
}
}
您不应该以编程方式更改卷,这就是
setVolume:
被弃用的全部要点。你的应用可能会被拒绝。SWIFTUI怎么办?我们怎么做?这有用吗?我试图使用它,但没有多大成功!我添加了一个视图并将其子类化到MPVolumeView,但它似乎不起作用。为我工作!谢谢!这非常有用,我在iOS 11.3上没有问题。我是在iOS 11.4上做的@OttoBoy@Karl-JohnChow我在这里添加了iOS 11.4上的工作解决方案,您应该如何使用它?Hi@JonathanPlackett,您可以这样尝试:self.volumeSlider.value=1//获取最大卷
BTW,self表示MPVolumeView实例。希望得到帮助。这对我在iOS8上有效,但对iOS9不起作用。是否有iOS9解决方案?在我的例子中,它在iOS 11.4中工作,只设置了更长的截止日期(例如,DispatchTime.now()+0.5)@AndreaGorrieri它仍能以0.01延迟工作,而不显示系统声条。看来你还有另外一个问题。不管怎样,把你的评论投给别人也有同样的问题。谢谢@据我所知,每当初始化MPVolumeView
时(从xib、故事板或编程方式),就会出现此警告。目前,它似乎仍然可以很好地处理此警告,并且没有人能够在这种情况下避免警告。@SimonPham我在iOS 12.0上尝试过,它可以正常工作。确保您在真实设备上运行,而不是在模拟器上运行。如果它仍然不起作用,您可以尝试增加延迟时间,正如上面AndreaGorrieri所说的那样。@SimonPham当然,您必须在前台调用它。使用ViewWillDisplay而不是ViewDidDisplay。
var systemVolume:Float {
get {
return hiddenSystemVolumeSlider.value
}
set {
hiddenSystemVolumeSlider.value = newValue
}
}