What should i know somethings about making custom ui through uikit in iOS?

I asked that related to making custom ui through uikit in iOS 2 days ago.

So, i maked custom ui through the way you taught me.

And then, I’m curious about somthings in that process.

  1. if i wanna use custom ui, can’t i use method already existed in player reference? and should i make needed function and event handler(ex. delegate pattern, notificaton, etc.) that like making custom ui?

When I make custom View like the part of player reference below

https://cdn.bitmovin.com/player/ios/3/docs/Classes/PlayerView.html

i wanna use methods that already existed in player reference but, picture in picture mode don’t operate.

so, i added a apple’s AVPictureInPictureController type’s instance property and i have been using picture in picture mode.

Like this case if i wanna use custom ui, i can’t use method already existed in player reference? and should i make needed function that like making custom ui? or is there other solution?

class TESTPlayerView: UIView {
    override class var layerClass: AnyClass {
        AVPlayerLayer.self
    }
    var player: Player? = nil
    
    var playerLayer: AVPlayerLayer {
        layer as! AVPlayerLayer
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        print("test- view initialized")
    }
    
    init(player: Player, frame: CGRect) {
        super.init(frame: frame)
        self.player = player
//        let subLayer = CALayer()
//        subLayer.frame = CGRect(x: 10, y: 10, width: 100, height: 100)
//        subLayer.backgroundColor = UIColor.yellow.cgColor
//
//        let subLayer2 = CALayer()
//        subLayer2.frame = CGRect(x: 120, y: 10, width: 100, height: 100)
//        subLayer2.backgroundColor = UIColor.blue.cgColor
//
//        let subLayer3 = CALayer()
//        subLayer3.frame = CGRect(x: 230, y: 10, width: 100, height: 100)
//        subLayer3.backgroundColor = UIColor.systemPink.cgColor
//
//        playerLayer.addSublayer(subLayer)
//        playerLayer.addSublayer(subLayer2)
//        playerLayer.addSublayer(subLayer3)
        
        let view1 = UIButton(frame: CGRect(x: 10, y: 10, width: 100, height: 50))
        view1.addTarget(self, action: #selector(didTapTouch), for: .touchUpInside)
        view1.backgroundColor = .systemBlue
        
//        let view2 = UIView(frame: CGRect(x: 120, y: 10, width: 100, height: 100))
        let view2 = UIButton(frame: CGRect(x: 120, y: 10, width: 100, height: 50))
        view2.addTarget(self, action: #selector(didTapTouch2), for: .touchUpInside)
        view2.backgroundColor = .systemYellow
        
//        let view3 = UIView(frame: CGRect(x: 230, y: 10, width: 100, height: 100))
        let view3 = UIButton(frame: CGRect(x: 230, y: 10, width: 100, height: 50))
        view3.addTarget(self, action: #selector(didTapTouch3), for: .touchUpInside)
        view3.backgroundColor = .systemPink
        
        self.addSubview(view1)
        self.addSubview(view2)
        self.addSubview(view3)
        
        self.player?.register(playerLayer)
    }
    
    @objc func didTapTouch() {
        player?.play()
    }
    
    @objc func didTapTouch2() {
        player?.pause()
    }
    
    @objc func didTapTouch3() {
        
    }
}
final class ViewController: UIViewController {
    var player: Player!
    var pictureInPictureController: AVPictureInPictureController?
    ...
    playerConfig.playbackConfig.isBackgroundPlaybackEnabled = true
    playerConfig.playbackConfig.isPictureInPictureEnabled = true
    player = PlayerFactory.create(playerConfig: config)
    
      let testPlayerView = TESTPlayerView(player: player, frame: .zero)
        
        self.pictureInPictureController = AVPictureInPictureController(playerLayer: testPlayerView.playerLayer)
        self.pictureInPictureController?.delegate = self

        player.add(listener: self)
        
//        playerView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        testPlayerView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height / 2)
        view.addSubview(testPlayerView)
        view.bringSubviewToFront(testPlayerView)
//        playerView.backgroundColor = .lightGray

        configureAudioSession()
        
        let sourceConfig = SourceConfig(url: streamUrl, type: .hls)
        player.load(sourceConfig: sourceConfig)
        
    }
    
    private func configureAudioSession() {
        let audioSession = AVAudioSession.sharedInstance()
        try? audioSession.setCategory(.playback)
    }
  1. How can i player view’s add(listener:) method in custom player view?
    Should i conform to what protocol and then typing concrete code?

  2. I wanna know somethings that conform to what protocols and where i typing concrete codes each code, when i wanna use to custom player view.

Hi @pdhou23,

It looks like the other post was pointing you into the wrong direction as it mentions the system UI and not a custom UIKit UI.

However, you are already on the right track with what I can see from your post.

  1. When creating a custom UI you need to take care of PiP on your own. This can be achieved with the AVPictureInPictureController as you seem to already doing it. You can then use startPictureInPicture and stopPictureInPicture to control the state.
  2. To receive events from the Player you can either use the listener (delegate) approach using the PlayerListener or through our new modern approach using the PlayerEventsApi.
  3. There are no additional protocol implementations needed when creating a custom UI.

Hope that helps. If you have any additional questions feel free to reply to this thread.