ScrollView惯性效果手动,iOS,Swift
Posted
技术标签:
【中文标题】ScrollView惯性效果手动,iOS,Swift【英文标题】:ScrollView inertia effect manually, 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在用户拿开手指后惯性移动时。谢谢。
【问题讨论】:
【参考方案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)
【讨论】:
以上是关于ScrollView惯性效果手动,iOS,Swift的主要内容,如果未能解决你的问题,请参考以下文章
android ScrollView 滑动特效 怎么做成iphone那样有惯性弹性!
Android ScrollView在滚动中调用scrollTo(0,0)回到顶部无效