简体   繁体   English

使用MPMediaPlayer Swift 4淡化(动画)音量

[英]Fade (animate) Volume using MPMediaPlayer Swift 4

I'm using Xcode 10+, Swift 4, and targeting iOS 11.4+ with MPMediaPlayer 我正在使用Xcode 10+,Swift 4,并使用MPMediaPlayer定位iOS 11.4+

I'd like to programmatically fade out the volume of the player (like Apple does when you quit their music player). 我想以编程方式淡出播放器的音量(就像Apple退出音乐播放器时那样)。 As well, I don't want to see anything (like the VolumeView display) when it functions. 同样,我不想在它运行时看到任何东西(比如VolumeView显示)。

It looks like all the programmatic volume controls have been deprecated. 看起来所有程序化的音量控件都已被弃用。

I've read through a lot of related posts and created this function which has several problems: 我已经阅读了很多相关帖子并创建了这个函数,它有几个问题:

@objc func fadeVolume(){
    var sliderView = UISlider()
    //let volumeView = MPVolumeView(frame: CGRect.init(x: self.view.frame.maxX, y: self.view.frame.maxY, width: 0, height: 0))
    let volumeView = MPVolumeView(frame: .zero)
    volumeView.clipsToBounds = true
    volumeView.showsRouteButton = false
    //volumeView.isHidden = true
    volumeView.alpha = 0.001
    for subview in volumeView.subviews {
        if let slider = subview as? UISlider {
            sliderView = slider
            break
        }
    }
    self.view.addSubview(volumeView)
    volumeView.didMoveToSuperview()

    let current:Float = AVAudioSession.sharedInstance().outputVolume
    print("slider value: \(current)")
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
        UIView.animate(withDuration: 0.4, animations: {
            sliderView.setValue(0.0, animated: false)
        }, completion: { finished in
            // If either one of these is uncommented, the VolumeView will display.
            // However, without removing from superview, the VolumeView stays hidden even when I use the phone volume buttons.
            volumeView.removeFromSuperview()
            //volumeView.alpha = 1.0
        })
    }
}

First problem: The VolumeView display shows onscreen. 第一个问题:VolumeView显示屏显示在屏幕上。 I've tried using different frames, and changing the alpha, etc. It's as though the animation never occurs and it goes directly to the completion block. 我尝试过使用不同的帧,更改alpha等等。就像动画永远不会发生一样,它直接进入完成块。

Second problem: The VolumeView really needs to be removed from the superview or else it will remain hidden even when I use the phone volume buttons. 第二个问题:VolumeView确实需要从superview中删除,否则即使我使用手机音量按钮它也会保持隐藏状态。 It should only be hidden during the execution of this function. 它只应在执行此功能时隐藏。

Third problem: The animate block does nothing. 第三个问题:动画块无效。 The volume will simply go from the starting point to 0 instantly - no fade. 音量将立即从起点变为0 - 不会褪色。

Fourth problem: I haven't tested this but my assumption is that this won't work when the app is in the background. 第四个问题:我没有对此进行测试,但我的假设是当应用程序在后台时这不起作用。 So the idea of using this to fade out the volume when quitting the app might not work. 所以在退出应用程序时使用它来淡出音量的想法可能不起作用。

Any idea how to fade out the volume without displaying anything onscreen? 知道如何淡出音量而不在屏幕上显示任何内容吗? The answer does not necessarily need to use MPVolumeView, but I need it to work with MPMediaPlayer and when exiting the App. 答案不一定需要使用MPVolumeView,但我需要它与MPMediaPlayer一起使用并在退出App时。

EDIT: Below is my modified code which will fade the volume, however the issue of being able to do this when my app terminates still exists. 编辑:下面是我修改后的代码,它将淡化卷,但是当我的应用程序终止时能够执行此操作的问题仍然存在。 I can call this code from 'appWillTerminate' however it does not run completely as the app terminates before it can loop through all the way. 我可以从'appWillTerminate'调用此代码但是它不能完全运行,因为应用程序终止之前它可以循环遍历。

// Public in ViewController Class:
let volumeView = MPVolumeView()
var sliderView = UISlider()
var currentVolume:Float = 0

//This called by a notification:
    @objc func fadeVolume(){
        // A lot of other posts use these to hide the volume view however I only needed the alpha change
        //volumeView.clipsToBounds = true
        //volumeView.showsRouteButton = false
        //volumeView.isHidden = true
        //print("volume alpha \(volumeView.alpha)")
        volumeView.alpha = 0.001
        self.view.addSubview(volumeView)
        volumeView.didMoveToSuperview()
        if let view = volumeView.subviews.first as? UISlider {
            sliderView = view
        }
        print("slider value: \(sliderView.value)")
        currentVolume = sliderView.value
        changeVolumeSlowly()
    }
    @objc func changeVolumeSlowly(){
        sliderView.value = sliderView.value - 0.1
        print("\(sliderView.value)")
        if sliderView.value > 0 {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
                self?.changeVolumeSlowly()
            }
        } else {
            myMP.pause()
            myMP.stop()
            //reset
            // Since the volumeView is 'global' to the app, if you do not change
            // it back to the previous volume and make it visible you won't see it unless you restart your app.
            //Unfortunately these cause the volume view to flash onscreen
            volumeView.alpha = 1.0
            sliderView.value = currentVolume
            volumeView.removeFromSuperview()
        }
    }

Make your UISlider variable public and use this function to fade the volume sound. 将您的UISlider变量公开,并使用此函数淡化音量。

@objc func changeVolumeSlowly(){
    sliderView.value = sliderView.value - 0.1
    print("\(sliderView.value)")
    if sliderView.value > 0 {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
            self?.changeVolumeSlowly()
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM