【问题标题】:ScrollView inertia effect manually, iOS, SwiftScrollView惯性效果手动,iOS,Swift
【发布时间】:2020-03-07 19:25:20
【问题描述】:

我有UICollectionView,我是从代码中拖出来的(不要问我为什么它很长:))。 我的代码运行良好:

func move(prevPoint: CGPoint, curPoint: CGPoint) {
    let xDiff = curPoint.x - prevPoint.x
    let yDiff = curPoint.y - prevPoint.y
    let xSign =  xDiff == 0 ? 1 : (xDiff / abs(xDiff))
    let ySign = yDiff == 0 ? 1 : (yDiff / abs(yDiff))

    let x = max(min(abs(xDiff), maxPickerStep), minPickerStep) * -xSign * xMultiplier
    let y = max(min(abs(yDiff), maxPickerStep), minPickerStep) * -ySign

    let offset = CGPoint(x: collectionView.contentOffset.x + x, y: collectionView.contentOffset.y)
    let cell = (collectionView.visibleCells.first as? ColorsCollectionViewCell)
    let innerOffset = cell?.colorCollectionView.contentOffset ?? .zero
    let inset = (cell?.colorCollectionView.contentInset.top ?? 0) * 2
    let innerYContentOffset = min(max(innerOffset.y + y, -inset), (cell?.colorCollectionView.contentSize.height ?? 0) - inset)

    cell?.colorCollectionView.contentOffset = CGPoint(x: innerOffset.x, y: innerYContentOffset)
    collectionView.contentOffset = offset
}

但是除了滚动之外,我想达到和UICollectionView一样的效果,当scrollView在用户拿开手指后惯性移动时。谢谢。

【问题讨论】:

    标签: ios swift uicollectionview uikit


    【解决方案1】:

    首先,我认为手动移动滚动视图肯定是我会避免的事情。 可能有一些更简单的东西可以满足您需要的行为。 因此,我强烈建议您和任何其他读者不要继续阅读这篇文章,而是继续尝试解决最初引导您到这里的问题。

    您还可以在 Stack Overflow 上提出另一个问题,以获得帮助以避免您手动更新 scrollView 位置。


    因此,如果您仍在阅读,this article 可能是实现真正感觉像 UIScrollView 的方法的方法。做任何其他事情可能看起来和感觉都很糟糕。

    基本上它包括使用 UIKit Dynamics 来控制惯性。

    因此,您可以创建一个符合 UIDynamicItem(具有非零 CGRect)的对象,并更改其中心而不是 scrollView contentOffset,而不是使用 UIDynamicAnimator 及其 UIDynamicBehavior 来设置惯性并在期间连接更改使用 UIDynamicBehavior 的 action block 将动画到 scrollView 中对应的 contentOffset。

    假设您有一个 UIDynamicItem 项目和一个 UIDynamicAnimator 动画器,panGesture 识别器的处理将如下所示:

    func handlGestureRecognizer(panGesture: UIPanGestureRecognizer) {
    
        switch panGesture.state {
        case .began:
            self.animator.removeAllBehaviors()
        case .changed:
            // Update scroll view position
            break
        case .ended:
            var velocity = panGesture.velocity(in: panGesture.view!)
            velocity.x = -velocity.x
            velocity.y = -velocity.y   
            // You probably need to check for out of bound velocity too, and also put velocity.x to 0 if the scroll is only scrolling vertically
    
            // This is done to just save the current content offset and then change it alongside the animation from this starting point         
            item.center = scrollView.contentOffset
    
            let decelerationBehavior = UIDynamicItemBehavior(items: [item])
            decelerationBehavior.addLinearVelocity(velocity, for: item)
            decelerationBehavior.resistance = 2.0
    
    
            decelerationBehavior.action = {
                // Connect the item center to the scroll contentOffset. Probably something like this:
                scrollView.contentOffset = item.center
            }
            self.animator.addBehavior(decelerationBehavior)
        default:
            break
        }
    }
    

    您不仅需要发挥行为的价值,并注意您在行为中投入的速度,还要特别注意查看边缘情况(例如,如果您滚动到最小值/最大值上)

    PS:毕竟我已经写了,我仍然认为你应该强烈考虑不要这样做,而是使用标准的 scrollView 滚动,避免手动更新。

    【讨论】:

    • 感谢您的回答@Enricoza,我稍微修改了您的解决方案(添加了resistance)并实现了预期的行为。谢谢!)
    • @TabulaRasa 是的,我忘了添加它...感谢您指出这一点,我已经编辑了答案以供将来参考。
    【解决方案2】:

    您可以尝试使用 decelerationRate 看看它是否满足您的需求。

     collectionView.decelerationRate = UIScrollView.DecelerationRate(rawValue: 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-18
      • 2012-02-17
      • 2012-06-24
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      相关资源
      最近更新 更多