IOS 9: Как изменить объем программно, не отображая всплывающее окно звуковой панели системы?

Я должен изменить громкость на iPad и использовать этот код:

[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];

Но это изменение объема и отображение панели громкости на iPad. Как изменить звук, не показывая громкость?

Я знаю, setVolume: устарел, и все говорят использовать MPVolumeView. Если это единственный способ решить мою проблему, то как изменить громкость с помощью MPVolumeView? Я не вижу никакого метода в MPVolumeView который меняет звук.
Должен ли я использовать другой класс вместе с MPVolumeView?

Но предпочтительнее использовать MPMusicPlayerController.

Спасибо за совет!

Ответ 1

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

Для 2018 года работает на iOS 11.4

Вам нужно изменить 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)

Версия Objective-C

Ответ 3

Я не думаю, что есть какой-либо способ изменить громкость без мигания регулятора громкости. Вы должны использовать 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];

Ответ 4

@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
    }
}

Ответ 5

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)

Ответ 6

Здесь решение в Swift. Это может быть теневой, поэтому я дам вам знать, одобрит ли Apple это, когда я опубликую. Между тем, это работает отлично для меня:

  • Определите MPVolumeView и дополнительный UISlider в вашем контроллере просмотра

    private let volumeView: MPVolumeView = MPVolumeView()
    private var volumeSlider: UISlider?
    
  • В раскадровке определите представление, которое скрыто от пользователя (height = 0 должно сделать трюк), и установите для него выход (мы будем называть его hiddenView здесь). Этот шаг хорош, если вы хотите НЕ отображать громкость HUD при изменении громкости (см. Примечание ниже):

    @IBOutlet weak var hiddenView: UIView!
    
  • В viewDidLoad() или где-нибудь в init-y, который выполняется один раз, поймайте UISlider, который фактически управляет томом в необязательном UISlider с шага (1):

    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
        }
    }
    

Важное примечание: Это решение будет предотвращать появление HUD объема громкости iPhone - либо при изменении громкости в коде, либо при нажатии пользователем внешних кнопок громкости. Если вы хотите отобразить HUD, то пропустите все скрытое представление, и не добавьте MPVolumeView в качестве подпрограммы вообще. Это приведет к тому, что iOS отобразит HUD при изменении громкости.

Ответ 7

Версия: 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
    }
}

Ответ 8

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
        }
    }
}

Ответ 9

Вы можете использовать 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

Свифт 4:

var player: AVPlayer!
...
player.volume = 0.5 // 50% level