'UICollectionView is unintentionally scrolling on button press

I have a UIButton added to a UICollectionViewCell, with a touch up event calling a method, that brings up a UIPopoverController, completely unrelated to the collection view.

Problem is when I press this button, my UICollectionView scrolls ever so slightly down. I cannot seem to figure out why. The scrolling actions are called before my button is actually pressed - so my attempts to prevent this form within the method called are futile.

Has anyone experienced this problem, or have any pointers on how to prevent it from happening?

I have tried disabling scrolling on the collection view on touch down, but it appears the touch down also triggers the scrolling - prior to the scroll disable.



Solution 1:[1]

To solve this problem, you should override func touchesShouldCancel

first, you create new class inherit UICollectionView, UITableView, UIScrollView.

In question, you want cancel in UICollectionView. so you make class inherit UICollectionCiew

seond, in func init you set property

self.delaysContentTouches = false
self.canCancelContentTouches = true

final, you override func touchesShouldCancel can cancel touch view kind In question, you want cancel in UIButton touch.

you make inherit class below code

import UIKit

class TouchCancelCollectionView: UICollectionView {

    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        self.delaysContentTouches = false
        self.canCancelContentTouches = true
    }

    required init(coder aDecoder: NSCoder) {
        fatalError()
    }

    override func touchesShouldCancel(in view: UIView) -> Bool {

        if view.isKind(of: UIButton.self) {
            return true
        }

        return super.touchesShouldCancel(in: view)
    }
}

and use it!

Solution 2:[2]

If I get your question right, I think this line of code could help you out.

yourCollectionView.delaysContentTouches = NO;

The problem is when there is a touch on the collectionView, the system doesn't know you are trying to click the button or scroll the view, so Apple gives scrolling higher priority. Hope this answer is right.

Feeling good to answer a question asked one year ago :)

Solution 3:[3]

I've tried to use answer from ??? and it was almost correct, but you must return false for view you don't want tracked. My implementation is for UIScrollView, but it's similar for UICollectionView.

final class NewScrollView: UIScrollView {
override init(frame: CGRect) {
    super.init(frame: frame)
    delaysContentTouches = false
    canCancelContentTouches = true
}

@available(*, unavailable)
required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func touchesShouldCancel(in view: UIView) -> Bool {
    if view is NameOfYourView {
        return false
    }

    return super.touchesShouldCancel(in: view)
}

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ???
Solution 2 Ke MA
Solution 3 jakub1984