Implemented pip function using AVPictureInPictureController. I hid the player and time search, but failed to hide the last close button and return button.
The buttons I want to hide are these buttons. enter image description here
The one I referenced is the following github.
https://github.com/uakihir0/UIPiPDemo
The source I used to declare AVPictureInPictureController is as follows.
import UIKit
import AVKit
class ViewController: UIViewController {
@IBOutlet weak var labelTest: UILabel!
private var pipUi = PipUi()
private var _pipController: AVPictureInPictureController?
private let _bufferDisplayLayer = AVSampleBufferDisplayLayer()
private var _pipPossibleObservation: NSKeyValueObservation?
private var _observer: NSObjectProtocol?
override func viewDidLoad() {
super.viewDidLoad()
let margin = ((view.bounds.width - 200) / 2)
let videoContainerView = UIView()
videoContainerView.frame = .init(x: margin, y: 200, width: 200, height: 30)
videoContainerView.backgroundColor = UIColor.blue
self.view.addSubview(videoContainerView)
let bufferDisplayLayer = pipUi.bufferDisplayLayer
bufferDisplayLayer.frame = videoContainerView.bounds
bufferDisplayLayer.backgroundColor = UIColor.brown.cgColor
bufferDisplayLayer.videoGravity = .resizeAspect
videoContainerView.layer.addSublayer(bufferDisplayLayer)
_bufferDisplayLayer.flush()
pipUi.start()
labelTest.setOnTouchListener(self, action: #selector(toggle))
DispatchQueue.main.async {
self.start()
}
}
func start() {
// PinP をサポートしているデバイスかどうかを確認
if AVPictureInPictureController.isPictureInPictureSupported() {
// AVPictureInPictureController の生成
_pipController = AVPictureInPictureController(
contentSource: .init(
sampleBufferDisplayLayer:
pipUi.bufferDisplayLayer,
playbackDelegate: self))
_pipController?.delegate = self
_pipPossibleObservation = _pipController?.observe(
\AVPictureInPictureController.isPictureInPicturePossible,
options: [.initial, .new],
changeHandler: { [weak self] _, changed in
DispatchQueue.main.async {
if changed.newValue == true {
//self?.start()
}
}
})
}
if #available(iOS 14.0, *) {
//Hide the seekbar
_pipController?.requiresLinearPlayback = true
} else {
// Fallback on earlier versions
}
//Hide the play/pause controls
_pipController?.setValue(true, forKey: "controlsStyle")
}
@objc func toggle() {
guard let _pipController = _pipController else { return }
if !_pipController.isPictureInPictureActive {
print("start")
_pipController.startPictureInPicture()
} else {
print("stop")
_pipController.stopPictureInPicture()
}
}
}
extension ViewController: AVPictureInPictureControllerDelegate {
func pictureInPictureController(
_ pictureInPictureController: AVPictureInPictureController,
failedToStartPictureInPictureWithError error: Error
) {
print("\(#function)")
print("pip error: \(error)")
}
func pictureInPictureControllerWillStartPictureInPicture(
_ pictureInPictureController: AVPictureInPictureController
) {
print("\(#function)")
}
func pictureInPictureControllerWillStopPictureInPicture(
_ pictureInPictureController: AVPictureInPictureController
) {
print("\(#function)")
}
}
extension ViewController: AVPictureInPictureSampleBufferPlaybackDelegate {
func pictureInPictureController(
_ pictureInPictureController: AVPictureInPictureController,
setPlaying playing: Bool
) {
print("\(#function)")
}
func pictureInPictureControllerTimeRangeForPlayback(
_ pictureInPictureController: AVPictureInPictureController
) -> CMTimeRange {
print("\(#function)")
return CMTimeRange(start: .negativeInfinity, duration: .positiveInfinity)
}
func pictureInPictureControllerIsPlaybackPaused(
_ pictureInPictureController: AVPictureInPictureController
) -> Bool {
print("\(#function)")
return false
}
func pictureInPictureController(
_ pictureInPictureController: AVPictureInPictureController,
didTransitionToRenderSize newRenderSize: CMVideoDimensions
) {
print("\(#function)")
print(newRenderSize)
}
func pictureInPictureController(
_ pictureInPictureController: AVPictureInPictureController,
skipByInterval skipInterval: CMTime,
completion completionHandler: @escaping () -> Void
) {
print("\(#function)")
completionHandler()
}
}
I want to hide the close button to customize it. please help.
I doubdt you can totally hide "close" and "return to app" buttons, becasue they are essential to PiP use and there is no API to hide them (as far as I know) . However if you tap into video screen, all buttons are temporarily hidden. Also those button are hidden automatically after 2 seconds of playback. Also Apple talkes about those buttons as mean of interaction with PiP in following support guide