Search code examples
swiftorientationmpmovieplayercontroller

MPMoviePlayerController custom control (subview)


I want to create a custom controller for MPMoviePlayerController. Everything works fine with the button, but when I rotate device, the subview (video controller) doesn't update the layout to fit the screen.

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    moviePlayer = MPMoviePlayerController(contentURL: urlVideo)
    moviePlayer.movieSourceType = MPMovieSourceType.Unknown
    moviePlayer.view.frame = self.view.bounds
    moviePlayer.scalingMode = MPMovieScalingMode.None
    moviePlayer.controlStyle = MPMovieControlStyle.None
    moviePlayer.shouldAutoplay = true
    moviePlayer.view.backgroundColor = UIColor.blackColor()
    self.view.addSubview(moviePlayer.view)
    moviePlayer.prepareToPlay()
    moviePlayer.play()

    var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTapGestureRecognizer")
    tapGestureRecognizer.delegate = self
    self.view.addGestureRecognizer(tapGestureRecognizer)

    // Do any additional setup after loading the view.
    self.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve;

    //       NSNotificationCenter.defaultCenter().addObserver(self, selector: "rotated", name: UIDeviceOrientationDidChangeNotification, object: nil)

    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updatePlaybackTime:", userInfo: nil, repeats: true)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("playerPlaybackDidFinish:"),
        name: MPMoviePlayerPlaybackDidFinishNotification, object: nil)

    NSNotificationCenter.defaultCenter() .addObserver(self, selector: "movieOrientationChanged", name: UIDeviceOrientationDidChangeNotification, object: nil)

    self.showController()
}

func showController() {
    doneButton = UIButton(frame: CGRectMake(0, 22, 50, 30))
    doneButton.backgroundColor = UIColor.redColor()
    doneButton.tintColor = UIColor.blackColor()
    doneButton.setTitle("Done", forState: .Normal)
    doneButton.addTarget(self, action: "exitVideo:", forControlEvents: UIControlEvents.TouchUpInside)
    self.controllerView.addSubview(doneButton)

    playButton = UIButton(frame: CGRectMake(0, self.view.bounds.size.height - 30, 60, 30))
    playButton.backgroundColor = UIColor.redColor()
    playButton.tintColor = UIColor.blackColor()
    playButton.addTarget(self, action: "pauseVideo:", forControlEvents: UIControlEvents.TouchUpInside)

    self.controllerView.addSubview(playButton)
    self.moviePlayer.view.addSubview(self.controllerView)

}

func movieOrientationChanged() {
    moviePlayer.view.frame = self.view.bounds
    controllerView.frame = self.moviePlayer.view.bounds
    self.showController()
}

1 - When the video player is opened

2 - When the video player is rotated to landscape

3 - When the video player is rotated back to portrait (there is still a red button in the middle of the video player) enter image description here


Solution

  • When the showController() function executed, you create a new doneButton and playButton into your view hierarchy. So when rotate to landscape, you will have two doneButton at the same position and two playButton in the different y-axis.

    Get it fixed quickly:

    func showController() {
        self.controllerView.subviews.map{ $0.removeFromSuperview() } // Added this line
    
        doneButton = UIButton(frame: CGRectMake(0, 22, 50, 30))
        doneButton.backgroundColor = UIColor.redColor()
        doneButton.tintColor = UIColor.blackColor()
        doneButton.setTitle("Done", forState: .Normal)
        doneButton.addTarget(self, action: "exitVideo:", forControlEvents: UIControlEvents.TouchUpInside)
        self.controllerView.addSubview(doneButton)
    
        playButton = UIButton(frame: CGRectMake(0, self.view.bounds.size.height - 30, 60, 30))
        playButton.backgroundColor = UIColor.redColor()
        playButton.tintColor = UIColor.blackColor()
        playButton.addTarget(self, action: "pauseVideo:", forControlEvents: UIControlEvents.TouchUpInside)
    
        self.controllerView.addSubview(playButton)
        self.moviePlayer.view.addSubview(self.controllerView)
    }