web-dev-qa-db-fra.com

iOS 9: Comment modifier le volume par programmation sans afficher de barre de son système?

Je dois changer le volume sur iPad et utiliser ce code:

[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];

Mais cela change le volume et affiche la barre de volume du système sur iPad. Comment changer le son sans afficher la barre de volume?

Je sais que setVolume: est obsolète et tout le monde dit d’utiliser MPVolumeView. Si c’est le seul moyen de résoudre mon problème, alors comment changer le volume avec MPVolumeView? Je ne vois aucune méthode dans MPVolumeView qui modifie le son. 
Devrais-je utiliser une autre classe avec MPVolumeView?

Mais il est préférable d'utiliser MPMusicPlayerController.

Merci pour le conseil!

12
mgv

MPVolumeView a un curseur, et en modifiant la valeur du curseur, vous pouvez modifier le volume du périphérique. J'ai écrit une extension MPVolumeView pour accéder facilement au curseur:

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

Pour 2018, travailler sur iOS 11.4

Vous devez changer slider.value après un petit délai.

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

Usage:

MPVolumeView.setVolume(0.5)

Version Objective-C

27
trungduc

Je ne pense pas qu'il y ait un moyen de changer le volume sans le faire clignoter Vous devriez utiliser MPVolumeView comme ceci:

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
Abhinav

La réponse de @udjat dans 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
    }
}
3
BumMo Koo

Version: 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
    }
}
2
Jerome
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()
      }
    }
  }
}

Usage:

// set volume to 50%
viewController.setVolume(0.5)
2
Senseful

Voici une solution dans Swift. C'est peut-être un peu louche, alors je vous ferai savoir si Apple a approuvé cela lorsque je publierai. En attendant, cela fonctionne très bien pour moi:

  1. Définir un MPVolumeView et un UISlider en option dans votre View Controller

    private let volumeView: MPVolumeView = MPVolumeView()
    private var volumeSlider: UISlider?
    
  2. Dans le storyboard, définissez une vue qui est masquée par l'utilisateur (height = 0 devrait suffire) et définissez un point de vente (nous l'appellerons hiddenView ici). Cette étape n’est utile que si vous ne souhaitez PAS afficher le HUD du volume lorsque vous le modifiez (voir la remarque ci-dessous):

    @IBOutlet weak var hiddenView: UIView!
    
  3. Dans viewDidLoad () ou quelque part par défaut init-y, exécutez UISlider qui contrôle réellement le volume dans UISlider facultatif à partir de l'étape (1):

    override func viewDidLoad() {
        super.viewDidLoad()
    
        ...
    
        hiddenView.addSubview(volumeView)
        for view in volumeView.subviews {
            if let vs = view as? UISlider {
                volumeSlider = vs
                break
            }
        }
    }
    
  4. Lorsque vous souhaitez définir le volume dans votre code, définissez simplement volumeSlider? .Value compris entre 0,0 et 1,0, par exemple. pour augmenter le volume:

    func someFunc() {
        if volumeSlider?.value < 0.99 {
            volumeSlider?.value += 0.01
        } else {
            volumeSlider?.value = 1.0
        }
    }
    

Remarque importante: Cette solution empêchera que la palette de volume de l'iPhone apparaisse - lorsque vous modifiez le volume dans votre code ou lorsque l'utilisateur clique sur les boutons de volume externes. Si vous souhaitez afficher la palette, ignorez tous les éléments de la vue masquée et n’ajoutez pas MPVolumeView en tant que sous-vue. Cela entraînera iOS pour afficher le HUD lorsque le volume change.

2
deebugger

Swift> 2.2, iOS> 8.0, 

Je n'ai trouvé aucune solution que je cherchais mais je finis par le faire comme solution:

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

Vous pouvez utiliser par défaut UISlider avec ce code:

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

suivant dans le code il suffit d'écrire

systemSlider.value = customSlide.value