检测用户何时滑过 UICollectionView 的 scrollViewWillBeginDragging 中的某个点?

问题描述

在我的 collectionView 中,单元格是整个屏幕的大小,我使用 vertical 滚动,并且我有 .isPagingEnabled = true。我需要防止用户快速滑动。更改 .decelerationRate 不起作用。我发现的唯一一件事是在用户滑动时禁用/启用 scrollView,这几乎可以正常工作。

在下图中,当开始滑动时,我禁用了 scrollView 并在顶部显示一个红色标签,上面写着“cv disabled”。当由于用户抬起手指而结束滑动时,我启用了 scrollView 并删除标签。但是,当我滑动一个细线并快速将手指从单元格中抬起时,红色标签永远不会消失并且滚动保持禁用状态。橙色箭头指向下一个带有米色背景的单元格,当我轻轻滑动时,该单元格即将显示

enter image description here

在下面的代码中,当滚动经过某个点(如全屏或四分之一屏幕)时,使用两者都尝试一切正常。问题是,如果我巧妙地滑动一个细线,scrollView 将保持禁用状态,因为 myScrollView?.isUserInteractionEnabled = true 所在的方法永远不会被触发。

第一次尝试:

var myScrollView: UIScrollView?

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

    if myScrollView == nil {
        myScrollView = scrollView
    }

    myScrollView?.isUserInteractionEnabled = false

    showReddisabledLabel()
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

    myScrollView?.isUserInteractionEnabled = true

    removeReddisabledLabel()
}

第二次尝试:

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

    if myScrollView == nil {
        myScrollView = scrollView
    }

    myScrollView?.isUserInteractionEnabled = false

    showReddisabledLabel()
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    NSObject.cancelPrevIoUsPerformRequests(withTarget: self)
    perform(#selector(uiscrollviewdelegate.scrollViewDidEndScrollingAnimation),with: nil,afterDelay: 0.3)
}

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

    myScrollView?.isUserInteractionEnabled = true

    removeReddisabledLabel()

    NSObject.cancelPrevIoUsPerformRequests(withTarget: self)
}

这个问题实际上只有在我滑动那个细线并快速抬起手指时才会发生,每隔一次,两次尝试的代码都可以完美运行。问题是scrollViewWillBeginDragging中,我如何检测用户何时滑过某个点,以便我可以设置myScrollView?.isUserInteractionEnabled = false

解决方法

我找不到一种方法来确定用户在 scrollViewWillBeginDragging 中滑动了多少,但我确实找到了解决细线滚动实际问题的方法。我把myScrollView?.isUserInteractionEnabled和redLabel分别放到各自的函数中,把这个answer和这个answer结合起来,创建了一个名为isScrolling的实例属性,用didSet来判断如果它正在滚动并从那里调用函数:

// Properties
var myScrollView: UIScrollView?

var isScrolling = false {
    didSet {

        if isScrolling {

            disableScrollView()

        } else {

            enableScrollView()
        }
    }
}

// My 2 Functions
func disableScrollView() {
    myScrollView?.isUserInteractionEnabled = false
    showRedDisabledLabel()
}

func enableScrollView() {
    myScrollView?.isUserInteractionEnabled = true
    removeRedDisabledLabel()
}

// UIScrollView Delegate Methods
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    
    if myScrollView == nil {
        myScrollView = scrollView
    }
    
    isScrolling = true
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView,willDecelerate decelerate: Bool) {
    
    if !decelerate {
        isScrolling = false
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    
    isScrolling = false
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    NSObject.cancelPreviousPerformRequests(withTarget: self)
    perform(#selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation),with: nil,afterDelay: 0.3)
}

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

    isScrolling = false
    NSObject.cancelPreviousPerformRequests(withTarget: self)
}