Long press gesture on UICollectionViewCell

前端 未结 8 1045
猫巷女王i
猫巷女王i 2020-11-27 09:46

I was wondering how to add a long press gesture recognizer to a (subclass of) UICollectionView. I read in the documentation that it is added by default, but I can\'t figure

8条回答
  •  借酒劲吻你
    2020-11-27 10:25

    Perhaps, using UILongPressGestureRecognizer is the most widespread solution. But I encounter with it two annoying troubles:

    • sometimes this recognizer works in incorrect way when we're moving our touch;
    • recognizer intercepts other touch actions so we can't use highlight callbacks of our UICollectionView in a proper way.

    Let me suggest one a little bit bruteforce, but working as it's required suggestion:

    Declaring a callback description for long click on our cell:

    typealias OnLongClickListener = (view: OurCellView) -> Void

    Extending UICollectionViewCell with variables (we can name it OurCellView, for example):

    /// To catch long click events.
    private var longClickListener: OnLongClickListener?
    
    /// To check if we are holding button pressed long enough.
    var longClickTimer: NSTimer?
    
    /// Time duration to trigger long click listener.
    private let longClickTriggerDuration = 0.5
    

    Adding two methods in our cell class:

    /**
     Sets optional callback to notify about long click.
    
     - Parameter listener: A callback itself.
     */
    func setOnLongClickListener(listener: OnLongClickListener) {
        self.longClickListener = listener
    }
    
    /**
     Getting here when long click timer finishs normally.
     */
    @objc func longClickPerformed() {
        self.longClickListener?(view: self)
    }
    

    And overriding touch events here:

    /// Intercepts touch began action.
    override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        longClickTimer = NSTimer.scheduledTimerWithTimeInterval(self.longClickTriggerDuration, target: self, selector: #selector(longClickPerformed), userInfo: nil, repeats: false)
        super.touchesBegan(touches, withEvent: event)
    }
    
    /// Intercepts touch ended action.
    override func touchesEnded(touches: Set, withEvent event: UIEvent?) {
        longClickTimer?.invalidate()
        super.touchesEnded(touches, withEvent: event)
    }
    
    /// Intercepts touch moved action.
    override func touchesMoved(touches: Set, withEvent event: UIEvent?) {
        longClickTimer?.invalidate()
        super.touchesMoved(touches, withEvent: event)
    }
    
    /// Intercepts touch cancelled action.
    override func touchesCancelled(touches: Set?, withEvent event: UIEvent?) {
        longClickTimer?.invalidate()
        super.touchesCancelled(touches, withEvent: event)
    }
    

    Then somewhere in controller of our collection view declaring callback listener:

    let longClickListener: OnLongClickListener = {view in
        print("Long click was performed!")
    }
    

    And finally in cellForItemAtIndexPath setting callback for our cells:

    /// Data population.
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
        let castedCell = cell as? OurCellView
        castedCell?.setOnLongClickListener(longClickListener)
    
        return cell
    }
    

    Now we can intercept long click actions on our cells.

提交回复
热议问题