0

I have a video in the background of every page of my scrollView with paging enabled. I want the video to play/pause when the area where one can see the video is tapped (see picture on the left below, between UIView containing label with name and image and bottom tab bar)(there is another subview over the video subview in each page: top info). The code used to achieve that is the following for loop (for loop because every page shall have these properties):

//add subviews (pages) for (pageIndex, page) in pagesViews.enumerated(){ //...create pages with views //add Subview with videoplayer frame to individual "pages" let videoPlayerFrame = CGRect(x: 0, y: 0, width: pageSize.width, height: pageSize.height) let videoPlayerView = PlayerView(frame: videoPlayerFrame) page.addSubview(videoPlayerView) //add Subview with top info frame to individual "pages" let postInfoFrame = CGRect(x: 0, y: 0, width: pageSize.width, height: 80) let infoView = PostView(frame: postInfoFrame) page.addSubview(infoView) //WORKS FINE UNTIL HERE //NEW SUBVIEW //add Subview with bottom info frame to individual "pages" let postPropertiesFrame = CGRect(x: 0, y: (pageSize.height - 200) / 2, width: pageSize.width, height: 200) let propertiesView = PostPropsView(frame: postPropertiesFrame) page.addSubview(propertiesView) } 

That's what it looks like if the new subview hasn't been added: WORKS UNTIL HERE

PlayerView class serving as basis of first subview, the video plays/pauses when I tap the video area (read comments to get overview first (e.g. spinner shouldn't be important)):

lass PlayerView: UIView { //create spinner view let activityIndicatorView: UIActivityIndicatorView = { //define properties let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge) aiv.translatesAutoresizingMaskIntoConstraints = false //start spinner aiv.startAnimating() return aiv }() //create controls container view containing the spinner let controlsContainerView: UIView = { //set properties of controls container view let controlView = UIView() controlView.backgroundColor = UIColor(white: 0, alpha: 1) return controlView }() override init(frame: CGRect){ super.init(frame: frame) //function below this override init setupPlayerView() //add subview with controls (e.g. spinner) controlsContainerView.frame = frame addSubview(controlsContainerView) //add to subview and center spinner in subview controlsContainerView.addSubview(activityIndicatorView) activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true //enable interaction controlsContainerView.isUserInteractionEnabled = true //function below this override init defInteractions() //backgorund color of player backgroundColor = .black } //define interactions (doupletap and singletap) func defInteractions (){ //singletap let singleTap = UITapGestureRecognizer(target: self, action: #selector(singleTapDetected(_:))) singleTap.numberOfTapsRequired = 1 //controlsContainerView controlsContainerView.addGestureRecognizer(singleTap) } //define type var player: AVPlayer? //set playing to false var isPlaying: Bool = false //PLAY?PAUSE VIDEO WHEN video tapped func singleTapDetected(_ sender: UITapGestureRecognizer) { //play or pause if(!isPlaying){ //play player?.play() isPlaying = true } else{ //pause player?.pause() isPlaying = false } } //setup video in background func setupPlayerView() { //insert url let urlString = "https://blurtime.com/images/testvideo.mov" //check URL if can be converted to NSURL if let videoURL = NSURL(string: urlString){ //player's video if self.player == nil { player = AVPlayer(url: videoURL as URL) } //add sub-layer let playerLayer = AVPlayerLayer(player: player) self.layer.addSublayer(playerLayer) playerLayer.frame = self.frame //when are frames actually rendered (when is video loaded) player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil) //loop through video NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: nil, using: { (_) in DispatchQueue.main.async { self.player?.seek(to: kCMTimeZero) self.player?.play() } }) } } //what to do when video is loaded (spinner shall disappear) override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { //when frames are actually being rendered if keyPath == "currentItem.loadedTimeRanges" { activityIndicatorView.stopAnimating() controlsContainerView.backgroundColor = .clear } } //reuired as suggested by XCode required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

However, if I add the subview with the PostPropsView class it doesn't completely work anymore. If the yellow areas are tapped it still functions as desired but not in the red area anymore... (picture on the right) Why does it work in the lower yellow area and why doesn't it anymore if the red area is tapped? Can anyone provide a solution (and explanation) to this problem?

2 Answers 2

2

The new view is on top of the view that has the tap gesture recognizer, and is intercepting those touches, and doesn't have a handler for them.

Perhaps create a new UIView, which contains both the PostPropsView and your video player, and put the tap gesture recognizer on that instead of the video? I don't believe you can add the UIView directly to the video player.

Sign up to request clarification or add additional context in comments.

Comments

2

As Jake T. said, the tap gesture recognizer is absorbing the tap, so what you have to do is to add this on your TapGesture declaration

let singleTap = UITapGestureRecognizer(target: self, action: #selector(singleTapDetected(_:))) singleTap.numberOfTapsRequired = 1 singleTap.cancelsTouchesInView = false 

With that, you'll get what you want

1 Comment

I've added singleTap.cancelsTouchesInView = false but it still doesn't work if I tap the red area... I'll just have to go with Jake T.s way I guess

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.