如何在 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 中会出错?

Swift - 移动到另一个场景时如何从场景中删除滑动手势?

如何在swift / SwiftUI中为滑动手势设置菜单栏图标的操作

Swift 3 中的滑动手势

在 Xcode 8.0 Swift 3.0 上检测手势

通过向左滑动选择 CollectionView 单元格(Swift 5)