如何在 swift 3 中将滑动手势添加到 AVPlayer
Posted
技术标签:
【中文标题】如何在 swift 3 中将滑动手势添加到 AVPlayer【英文标题】:How can I add Swipe Gesture to AVPlayer in swift 3 【发布时间】:2017-05-31 14:56:58 【问题描述】:我正在使用 Swift 3,我想将滑动手势添加到 AVPlayer
。有人告诉我,为了做到这一点,我必须使用另一个视图并将该视图带到视频的顶部 - 所以我做到了,这是我的代码:(但没有用 ) :(
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController , UIAlertViewDelegate
let myFirstButton = UIButton()
let mySecondButton = UIButton()
var scoreLabel = UILabel()
var Player = AVPlayer()
var swipeGesture = UIGestureRecognizer()
var sView = UIView()
override func viewDidLoad()
super.viewDidLoad()
////////////
sView.frame = self.view.frame
self.view.addSubview(sView)
self.view.bringSubview(toFront: sView)
//////Swipe Gesture
let swipeRight = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
swipeRight.direction = UISwipeGestureRecognizerDirection.right
self.sView.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
swipeLeft.direction = UISwipeGestureRecognizerDirection.left
self.sView.addGestureRecognizer(swipeLeft)
let swipeUp = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
swipeUp.direction = UISwipeGestureRecognizerDirection.up
self.sView.addGestureRecognizer(swipeUp)
let swipeCustom = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
swipeCustom.direction = UISwipeGestureRecognizerDirection.init(rawValue: 200)
self.sView.addGestureRecognizer(swipeCustom)
let swipeDown = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
swipeDown.direction = UISwipeGestureRecognizerDirection.down
self.sView.addGestureRecognizer(swipeDown)
//////////////////////End Swipe Gesture
let currentPlayerItem = Player.currentItem
let duration = currentPlayerItem?.asset.duration
let currentTime = Float(self.Player.currentTime().value)
if currentTime >= 5
print("OK")
else if currentTime <= 5
print("NO")
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.Player.currentItem, queue: nil, using: (_) in
DispatchQueue.main.async
self.Player.seek(to: kCMTimeZero)
self.Player.play()
)
/////////////
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.Player.currentItem, queue: nil, using: (_) in
DispatchQueue.main.async
self.Player.seek(to: kCMTimeZero)
self.Player.play()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5.0)
// check if player is still playing
if self.Player.rate != 0
print("OK")
print("Player reached 5 seconds")
)
fileprivate var firstAppear = true
//////Swipe Gesture
func respondToSwipeGesture(gesture: UIGestureRecognizer)
if let swipeGesture = gesture as? UISwipeGestureRecognizer
switch swipeGesture.direction
case UISwipeGestureRecognizerDirection.right:
print("Swiped right")
case UISwipeGestureRecognizerDirection.down:
print("Swiped down")
case UISwipeGestureRecognizerDirection.left:
print("Swiped left")
case UISwipeGestureRecognizerDirection.up:
print("Swiped up")
case UISwipeGestureRecognizerDirection.init(rawValue: 200):
print("Swiped Custom")
default:
break
/////////End Swipe Gesture
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
if firstAppear
do
try playBackgroundMovieVideo()
firstAppear = false
catch AppError.invalidResource(let NMNF6327, let m4v)
debugPrint("Could not find resource \(NMNF6327).\(m4v)")
catch
debugPrint("Generic error")
override var supportedInterfaceOrientations: UIInterfaceOrientationMask
return UIInterfaceOrientationMask.landscapeLeft
fileprivate func playBackgroundMovieVideo() throws
guard let path = Bundle.main.path(forResource: "NMNF6327", ofType:"m4v") else
throw AppError.invalidResource("NMNF6327", "m4v")
self.Player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.view.isUserInteractionEnabled = true
playerController.player = self.Player
playerController.viewWillLayoutSubviews()
playerController.allowsPictureInPicturePlayback = false
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
myFirstButton.frame = CGRect(x: 5, y: 5, width: 70, height: 50)
self.myFirstButton.addTarget(self, action:#selector(self.myFirstButtonpressed), for: .touchUpInside)
self.view.addSubview(myFirstButton)
playerController.view.addSubview(myFirstButton)
mySecondButton.setImage(#imageLiteral(resourceName: "Options.png"), for: UIControlState.normal)
mySecondButton.frame = CGRect(x: 60, y: 5, width: 70, height: 50)
self.mySecondButton.addTarget(self, action:#selector(self.mySecondButtonClicked), for: .touchUpInside)
self.view.addSubview(mySecondButton)
playerController.view.addSubview(mySecondButton)
self.present(playerController, animated: false)
self.Player.play()
func playerDidReachEnd(notification: NSNotification)
self.Player.seek(to: kCMTimeZero)
self.Player.play()
func myFirstButtonpressed(sender: UIButton!)
myFirstButton.setImage(#imageLiteral(resourceName: "Play.png"), for: UIControlState.normal)
let alertView = UIAlertView();
alertView.addButton(withTitle: "Continue");
alertView.delegate=self;
alertView.addButton(withTitle: "restart");
alertView.addButton(withTitle: "Middle");
alertView.title = "PAUSE";
alertView.message = "";
alertView.show();
let playerController = AVPlayerViewController()
playerController.viewWillLayoutSubviews()
self.present(playerController , animated: true)
self.Player.pause()
func mySecondButtonClicked()
func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int)
if buttonIndex == 0
self.Player.play()
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
print("Continue")
else if buttonIndex == 1
self.Player.seek(to: kCMTimeZero)
self.Player.play()
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
////Middle
else if buttonIndex == 2
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
let timeScale = self.Player.currentItem?.asset.duration.timescale;
let time = CMTimeMakeWithSeconds( +9 , timeScale!)
self.Player.seek(to: time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
self.Player.play()
override var shouldAutorotate: Bool
return false
func update()
myFirstButton.isHidden=false
enum AppError : Error
case invalidResource(String, String)
【问题讨论】:
这些是我所有的代码,我已经在另一个项目中测试了这些代码并且它们运行良好 您是否已将sView
添加为子视图?
是的,正如您在代码中看到的那样,我使用 self.view.bringSubview(toFront: sView) 将其带到了顶部
我也将 sview 添加为子视图,但这里也没有得到答案是 self.view.addSubview(sView) 方法
用AVPlayerViewController怎么样?
【参考方案1】:
您的代码有两个错误。
1.在错误的控制器视图上添加手势视图。您不是在 AVPlayerViewController() 中添加手势视图,而是在初始控制器上添加,在呈现后将被 AVPlayerViewController() 覆盖。
3.选择器的目标错误 您在 let swipeRight = UISwipeGestureRecognizer(target: sView, action: #selector(self.respondToSwipeGesture))
上对 target 做出错误假设。您正在将目标设置为 sView 并在 ViewController 上实现选择器方法。
这里的target表示选择器方法的目标对象。所以将目标更改为自我(即您的视图控制器)将使您的视图控制器成为选择器方法func respondToSwipeGesture(gesture: UIGestureRecognizer)
的目标
请参考以下更正的代码。
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController , UIAlertViewDelegate
let myFirstButton = UIButton()
let mySecondButton = UIButton()
var scoreLabel = UILabel()
var Player = AVPlayer()
var swipeGesture = UIGestureRecognizer()
var sView = UIView()
override func viewDidLoad()
super.viewDidLoad()
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeRight.direction = UISwipeGestureRecognizerDirection.right
self.sView.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeLeft.direction = UISwipeGestureRecognizerDirection.left
self.sView.addGestureRecognizer(swipeLeft)
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeUp.direction = UISwipeGestureRecognizerDirection.up
self.sView.addGestureRecognizer(swipeUp)
let swipeCustom = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeCustom.direction = UISwipeGestureRecognizerDirection.init(rawValue: 200)
self.sView.addGestureRecognizer(swipeCustom)
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeDown.direction = UISwipeGestureRecognizerDirection.down
self.sView.addGestureRecognizer(swipeDown)
//////////////////////End Swipe Gesture
let currentPlayerItem = Player.currentItem
let duration = currentPlayerItem?.asset.duration
let currentTime = Float(self.Player.currentTime().value)
if currentTime >= 5
print("OK")
else if currentTime <= 5
print("NO")
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.Player.currentItem, queue: nil, using: (_) in
DispatchQueue.main.async
self.Player.seek(to: kCMTimeZero)
self.Player.play()
)
/////////////
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.Player.currentItem, queue: nil, using: (_) in
DispatchQueue.main.async
self.Player.seek(to: kCMTimeZero)
self.Player.play()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5.0)
// check if player is still playing
if self.Player.rate != 0
print("OK")
print("Player reached 5 seconds")
)
fileprivate var firstAppear = true
//////Swipe Gesture
func respondToSwipeGesture(gesture: UIGestureRecognizer)
if let swipeGesture = gesture as? UISwipeGestureRecognizer
switch swipeGesture.direction
case UISwipeGestureRecognizerDirection.right:
print("Swiped right")
case UISwipeGestureRecognizerDirection.down:
print("Swiped down")
case UISwipeGestureRecognizerDirection.left:
print("Swiped left")
case UISwipeGestureRecognizerDirection.up:
print("Swiped up")
case UISwipeGestureRecognizerDirection.init(rawValue: 200):
print("Swiped Custom")
default:
break
/////////End Swipe Gesture
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
if firstAppear
do
try playBackgroundMovieVideo()
firstAppear = false
catch AppError.invalidResource(let NMNF6327, let m4v)
debugPrint("Could not find resource \(NMNF6327).\(m4v)")
catch
debugPrint("Generic error")
override var supportedInterfaceOrientations: UIInterfaceOrientationMask
return UIInterfaceOrientationMask.landscapeLeft
fileprivate func playBackgroundMovieVideo() throws
guard let path = Bundle.main.path(forResource: "NMNF6327", ofType:"m4v") else
throw AppError.invalidResource("NMNF6327", "m4v")
self.Player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
playerController.view.isUserInteractionEnabled = true
playerController.player = self.Player
playerController.viewWillLayoutSubviews()
playerController.allowsPictureInPicturePlayback = false
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
myFirstButton.frame = CGRect(x: 5, y: 5, width: 70, height: 50)
self.myFirstButton.addTarget(self, action:#selector(self.myFirstButtonpressed), for: .touchUpInside)
self.view.addSubview(myFirstButton)
mySecondButton.setImage(#imageLiteral(resourceName: "Options.png"), for: UIControlState.normal)
mySecondButton.frame = CGRect(x: 60, y: 5, width: 70, height: 50)
self.mySecondButton.addTarget(self, action:#selector(self.mySecondButtonClicked), for: .touchUpInside)
self.view.addSubview(mySecondButton)
sView.frame = self.view.frame
playerController.view.addSubview(sView)
playerController.view.bringSubview(toFront: sView)
// ****** buttons are added after sview **********
playerController.view.addSubview(myFirstButton)
playerController.view.addSubview(mySecondButton)
self.present(playerController, animated: false)
self.Player.play()
func playerDidReachEnd(notification: NSNotification)
self.Player.seek(to: kCMTimeZero)
self.Player.play()
func myFirstButtonpressed(sender: UIButton!)
myFirstButton.setImage(#imageLiteral(resourceName: "Play.png"), for: UIControlState.normal)
let alertView = UIAlertView();
alertView.addButton(withTitle: "Continue");
alertView.delegate=self;
alertView.addButton(withTitle: "restart");
alertView.addButton(withTitle: "Middle");
alertView.title = "PAUSE";
alertView.message = "";
alertView.show();
let playerController = AVPlayerViewController()
playerController.viewWillLayoutSubviews()
self.present(playerController , animated: true)
self.Player.pause()
func mySecondButtonClicked()
func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int)
if buttonIndex == 0
self.Player.play()
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
print("Continue")
else if buttonIndex == 1
self.Player.seek(to: kCMTimeZero)
self.Player.play()
//myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
////Middle
else if buttonIndex == 2
myFirstButton.setImage(#imageLiteral(resourceName: "pause.png"), for: UIControlState.normal)
let timeScale = self.Player.currentItem?.asset.duration.timescale;
let time = CMTimeMakeWithSeconds( +9 , timeScale!)
self.Player.seek(to: time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
self.Player.play()
override var shouldAutorotate: Bool
return false
func update()
myFirstButton.isHidden=false
enum AppError : Error
case invalidResource(String, String)
【讨论】:
它工作但我不能使用按钮!我可以将它们添加到 sview 中吗? 只有在添加了 sview 之后才添加按钮!查看更新的代码 请投票给我的问题【参考方案2】:斯威夫特 4
不用sView也可以,只需在AVPlayerViewController的视图中添加手势识别器即可:
func playVideo()
let playerController = AVPlayerViewController()
playerController.player = AVPlayer(url: URL(fileURLWithPath: videoPath))
playerController.showsPlaybackControls = false
playerController.view.isUserInteractionEnabled = true
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
swipeUp.direction = UISwipeGestureRecognizerDirection.up
playerController.view.addGestureRecognizer(swipeUp)
present(playerController, animated: false)
playerController.player?.play()
@objc func respondToSwipeGesture(gesture: UIGestureRecognizer)
print("swipe up")
【讨论】:
谢谢,它有帮助!不幸的是,在较新的 ios 上(我认为从 11 开始),滑动会导致在控制器中移动视频,并且似乎优先于UISwipeGestureRecognizer
。你知道有什么方法可以防止这种情况发生吗?【参考方案3】:
您可能需要正确初始化 sView。确保将所需的框架分配给 sView 并将其作为子视图添加到 self.view。
override func viewDidLoad()
super.viewDidLoad()
sView.frame = self.view.frame
self.view.addSubview(sView)
self.view.bringSubview(toFront: sView)
// add you gestures to sView here ...
【讨论】:
没有用请帮我获得礼物的声誉 我不明白什么是问题。使用 AVPlayer 和正在工作的手势创建示例项目here 我在 GitHub 中检查了你的代码,但仍然不适合我,请帮我获得 50 声望 好吧,在你的情况下,我唯一能做的就是调试你的代码示例,如果你与 *** 社区分享的话。 好的,请稍等,今晚我将把所有代码放在这里(编辑问题)【参考方案4】:你应该这样做:playerController.view.addSubview(self.sView)
而不是self.view.addSubview(sView)
你应该像这样将 self 添加为 tagart:
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
它会起作用的。这是我的控制台:https://i.stack.imgur.com/agaBx.jpg
【讨论】:
以上是关于如何在 swift 3 中将滑动手势添加到 AVPlayer的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 移动到另一个场景时如何从场景中删除滑动手势?