I. Open lesson
Hello dear friends. We meet again in the cool seasonal weather, this code must know you all right ). The story is that I had a high school friend all day long. I could only go on a trip, it was so crazy that I traveled by motorbike from the North to the South because of my passion. Wherever it goes, it also records videos and then uploads them on YouTube. The thing that it invested in is also “genuine” equipment so videos are very good quality. Hoa Binh flood discharge just now it stood next to the flood flow. Then he also thought of ways to commercialize the effort he put into it. It asked me to create an app and sell content, but after thinking about it, it decided to upload it to youtube for free
). I have to do it again and have to give up and in this app I have learned a pretty simple but interesting skill to share with you. That’s how to zoom in, zoom out videoplayer like the youtube app we use often. Come on rambling too much, we start home.
II. Implement
I would like to burn the stage and show UI screen including:
- 1 is videoPlayer (here I use YouTubePlayerView is YouTubePlayer-Swift lib to play link from youtube’s api). You can use AVPlayer if the usual video shows we do. These 2 are essentially the same and can customize the layout as you like.
- 2 is the list of related videos.
And the problem is that the videoPlayer zoom is smaller in the corner of the screen to select other videos on the Home screen like this image:
To zoom in or zoom out I choose UIPanGestureRecognizer. Perhaps this is also difficult for you to understand and now start the steps to do.
Step 1: We create 2 enum. 1 is to determine the status of VideoPlayer, 1 enum to navigate
1 2 3 4 5 6 7 8 9 10 11 12 13 | enum StateVideoPlayer { case minimized case fullScreen case hidden } enum Direction { case up case down case right case left case none } |
Step 2: Initialize p Step 2: Initialize UIPanGestureRecognizer with target and action, add gestureRecognizer to VideoPlayer
1 2 3 | let panGesture: UIPanGestureRecognizer = UIPanGestureRecognizer.init(target: self, action: #selector(self.minimizeGesture(_:))) videosPlayer.addGestureRecognizer(panGesture) |
Step 3: Processing code in panuncest func selector As we all know, UIPanGestureRecognizer has 6 states but here I only need to use 2 states to handle that: began and ended The purpose of this func is to identify the user want to move VideoPlayer in any direction and in which state VideoPlayer is with 2 enum created in step 1 Then we will take velocity to change VideoPlayer frame is ok. I have handled the following:
Create a function with the translation and state input of VideoPlayer. This function changes the coordinates for VideoPlayer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | func positionDuringSwipe(translation: CGFloat, toState: StateVideoPlayer) { let width = UIScreen.main.bounds.width * 0.5 * translation let height = width * 9 / 16 let x = (UIScreen.main.bounds.width - 10) * translation - width let y = (UIScreen.main.bounds.height - 10) * translation - height let coordinate = CGPoint.init(x: x, y: y) switch toState { case .fullScreen: self.view.frame.origin = coordinate case .hidden: self.view.frame.origin.x = UIScreen.main.bounds.width/2 + translation - 10 case .minimized: self.view.frame.origin = coordinate } } |
There are slightly puzzling parameters here as 9/16 I have explained a bit. Usually when layout for a videoplayer we usually set the width ratio, height is 16: 9 (The standard ratio for displaying videos, you can search this ratio in google to understand and deeper).
Next create a function with the input scaleFactor. This function changes transform for VideoPlayer
1 2 3 4 5 6 7 | func changeValues(scaleFactor: CGFloat) { self.tableView.alpha = 1 - scaleFactor let scale = CGAffineTransform.init(scaleX: (1 - 0.5 * scaleFactor), y: (1 - 0.5 * scaleFactor)) let transform = scale.concatenating(CGAffineTransform.init(translationX: -(self.videosPlayer.bounds.width / 4 * scaleFactor), y: -(self.videosPlayer.bounds.height / 4 * scaleFactor))) self.videosPlayer.transform = transform } |
Now the func selector of UIPanGestureRecognizer will determine our problem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | @objc fileprivate func minimizeGesture(_ sender: UIPanGestureRecognizer) { if sender.state == .began { let velocity = sender.velocity(in: nil) let vecX = velocity.x let vecY = velocity.y if vecX > 0 && vecY > 0 { self.direction = .down } else if vecX < 0 && vecY < 0 { self.direction = .up } else if vecX < 0 && vecY >= 0 { self.direction = .left } else if vecX > 0 && vecY <= 0 { self.direction = .right } } var finalState = StateVideoPlayer.fullScreen switch self.state { case .fullScreen: let factor = (abs(sender.translation(in: nil).y) / UIScreen.main.bounds.height) self.changeValues(scaleFactor: factor) self.positionDuringSwipe(translation: factor, toState: .minimized) finalState = .minimized case .minimized: if self.direction == .left || self.direction == .right { finalState = .hidden let factor: CGFloat = sender.translation(in: nil).x self.positionDuringSwipe(translation: factor, toState: .hidden) } else { finalState = .fullScreen let factor = 1 - (abs(sender.translation(in: nil).y) / UIScreen.main.bounds.height) self.changeValues(scaleFactor: factor) self.positionDuringSwipe(translation: factor, toState: .fullScreen) } default: break } if sender.state == .ended { self.state = finalState self.animate() self.delegate?.didEndedSwipe(toState: self.state, direction: self.direction) if self.state == .hidden { self.videosPlayer.pause() } } } |
III. See you again
That’s it! Let’s build and try. If there is anything not understood or comment I will explain. Have a nice day.