更新滚动视图中的 targetContentOffsetWillEndDragging 到错误方向的值不会动画

问题描述 投票:0回答:2

我在

targetContentOffset
中为
scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)
设置一个新值,以在
UITableView
中创建自定义分页解决方案。当为
targetContentOffset
设置与速度指向相同的滚动方向的坐标时,它会按预期工作。

但是,当沿速度的相反方向“向后”捕捉时,它会立即“向后捕捉”而没有动画。这看起来很糟糕。关于如何解决这个问题的任何想法。

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    // a lot of caluculations to detemine where to "snap scroll" to
    if shouldSnapScrollUpFromSpeed || shouldSnapScrollUpFromDistance {
        targetContentOffset.pointee.y = -scrollView.frame.height
    } else if shouldSnapScrollDownFromSpeed || shouldSnapScrollDownFromDistance {
        targetContentOffset.pointee.y = -detailViewHeaderHeight
    }
}

我可以潜在地计算这个“错误”何时会出现,也许使用另一种“快速滚动”方式。关于如何使用

targetContentOffset.pointee.y
正常执行此操作或解决它的任何建议?

uitableview cocoa-touch uiscrollview uiscrollviewdelegate
2个回答
1
投票

我找到了一个好的解决方案(或解决方法)。让我知道是否有人有更好的解决方案。

我只是检测到何时会出现不需要的“非动画快照滚动”,然后我没有将新值设置为

targetContentOffset.pointee.y
而是将其设置为当前偏移值(停止它)并使用scrollViews设置所需的偏移目标值
 setContentOffset(_:animated:)
代替

if willSnapScrollBackWithoutAnimation {
    targetContentOffset.pointee.y = -scrollView.frame.height+yOffset //Stop the scrolling
    shouldSetTargetYOffsetDirectly = false
}

if let newTargetYOffset = newTargetYOffset {
    if shouldSetTargetYOffsetDirectly {
        targetContentOffset.pointee.y = newTargetYOffset
    } else {
        var newContentOffset = scrollView.contentOffset
        newContentOffset.y = newTargetYOffset
        scrollView.setContentOffset(newContentOffset, animated: true)
    }
}

0
投票

IMO 这个问题的唯一解决方案是“@sunkas 解决方案”。它在概念上很简单,但需要注意大量细节。

func scrollViewWillEndDragging(_ sv: UIScrollView,
  withVelocity vel: CGPoint,
  targetContentOffset: UnsafeMutablePointer<CGPoint>) {

  print("Apple wants to end at \(targetContentOffset.pointee)")
  ...

假设 UIKit 希望抛出结束于“355.69”。

  ...
  ... your calculations and logic
  solve = 280

你做你的计算和逻辑。您希望投掷在 280 时结束。

实际上就这么简单,从概念上讲:

  ... your calculations and logic
  solve = 280
targetContentOffset.pointee.y = solve
UIView.animate(withDuration: secs, delay: 0, options: .curveEaseOut, animations: {
    theScroll.contentOffset.y = solve
})

仅此而已。

然而,要获得与 UIKit 行为和感觉相匹配的完美结果,还有很多复杂的因素。

  • 弄清楚你的“解决方案”是一项艰巨的任务,你希望它下一个降落的地方.

  • 你需要很多代码来决定用户是否真的扔了它(到你的下一个停止位置),或者,他们是否只是“移动他们的手指一点点,然后松开”

  • 如果他们只是“稍微移动一下手指,然后放开”,您必须决定您的下一个解决方案是他们开始的那个,“下一个”还是“前一个”您的点击停止 .

  • 一个困难的问题是,在现实中你会想为它制作动画使用弹簧物理以匹配UIKit会做的正常停止

  • 更棘手的是,当你做弹簧动画时,你需要计算并匹配手指的投掷速度否则它看起来不对

这真是一件苦差事。

© www.soinside.com 2019 - 2024. All rights reserved.