首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UISnapBehavior可能和UIScrollview一起使用吗?

UISnapBehavior可能和UIScrollview一起使用吗?
EN

Stack Overflow用户
提问于 2016-07-19 18:01:57
回答 2查看 743关注 0票数 2

我正在试图找出是否可以使用来自UIAnimator的UIAnimator中的一个UIScrollview来使滚动视图的内容变得更加突出。到目前为止,我的发现已经导致这是不可能的。

我正在努力实现的

当用户拖动滚动视图时,UIScrollView将“快照”到一定的位置。然而,滚动必须从抓拍的位置恢复,而不需要用户举起触点。

苹果似乎在他们的iOS照片应用程序的照片编辑中实现了这一点。(见下面的截图)

我试过什么

我试图通过将UIPanGestureRecognizer附加到滚动视图并使用它的速度来获得此行为。如果用户正在向快照点拖动,滚动视图将禁用滚动,动画到快照点,当完成动画时,它将重新启用滚动。

但是,这会导致用户在拖动并重新拖动滚动视图后必须抬起触点的问题。然而,苹果似乎已经做到了这一点,而不必解除阻力。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-26 13:36:56

我试着模仿iOS照片应用程序。以下是我的逻辑:

代码语言:javascript
复制
// CALCULATE A CONTENT OFFSET FOR SNAPPING POINT 
let snapPoint = CGPoint(x: 367, y: 0)  

// CHANGE THESE VALUES TO TEST
let minDistanceToSnap = 7.0
let minVelocityToSnap = 25.0
let minDragDistanceToReleaseSnap = 7.0
let snapDuringDecelerating = false

这种滚动需要三个阶段。

代码语言:javascript
复制
enum SnapState {
case willSnap
case didSnap
case willRelease
}
  1. willSnap:默认状态。决定什么时候拍。比较contentOffset distance from SnapPoint with minDistanceToSnapscrollview velocity with minVelocityToSnap。更改为didSnap状态。
  2. didSnap:手动setContentOffset到提供的contextOffset(snapPoint)。在dragDistance上计算scrollView。如果用户拖动超过一定距离(minDragDistanceToReleaseSnap),则更改为willRelease状态。
  3. 如果willRelease:大于minDistanceToSnap,则distance scroll from snapPoint再次更改为willSnap状态。
代码语言:javascript
复制
extension ViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(scrollView: UIScrollView) {
        switch(snapState) {
            case .willSnap:
                let distanceFromSnapPoint = distance(between: scrollView.contentOffset, and: snapPoint)
                let velocity = scrollView.panGestureRecognizer.velocityInView(view)
                let velocityDistance = distance(between: velocity, and: CGPointZero)
                if distanceFromSnapPoint <= minDistanceToSnap && velocityDistance <= minVelocityToSnap && (snapDuringDecelerating || velocityDistance > 0.0) {
                    startSnapLocaion = scrollView.panGestureRecognizer.locationInView(scrollView)
                    snapState = .didSnap
                }
            case .didSnap:
                scrollView.setContentOffset(snapPoint, animated: false)
                var dragDistance = 0.0
                let location = scrollView.panGestureRecognizer.locationInView(scrollView)
                dragDistance = distance(between: location, and: startSnapLocaion)
                if dragDistance > minDragDistanceToReleaseSnap  {
                    startSnapLocaion = CGPointZero
                    snapState = .willRelease
                }
            case .willRelease:
                let distanceFromSnapPoint = distance(between: scrollView.contentOffset, and: snapPoint)
                if distanceFromSnapPoint > minDistanceToSnap {
                    snapState = .willSnap
                }
        }
    }
}

辅助函数

代码语言:javascript
复制
func distance(between point1: CGPoint, and point2: CGPoint) -> Double {
    return Double(hypotf(Float(point1.x - point2.x), Float(point1.y - point2.y)))
}

做了一个在Github上的演示项目:https://github.com/rishi420/SnapDrag

注:用Xcode 7.2制作的项目。您可能需要修改一下才能编译。

票数 4
EN

Stack Overflow用户

发布于 2016-07-23 00:18:21

不要将UIPanGestureRecognizer直接添加到UIScrollView中。相反,将其添加到容器视图中,然后在选择器中手动设置UIScrollView contentOffset。

禁用UIScrollView本身上的交互,或使用委托来防止与滚动视图的直接交互。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38465498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档