UIAnimator 的 UISnapBehavior 可能与 UIScrollview 一起使用吗? [英] UIAnimator's UISnapBehavior possible with UIScrollview?

查看:23
本文介绍了UIAnimator 的 UISnapBehavior 可能与 UIScrollview 一起使用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚是否可以在 UIScrollview 内使用 UIAnimator 的 UISnapBehavior 来使滚动视图的内容对齐到一个点.到目前为止,我的研究结果表明这是不可能的.

我正在努力实现的目标

UIScrollView 在用户拖动滚动视图时对齐"到某个点.但是,滚动必须从对齐位置恢复,而用户不必抬起触摸.

Apple 似乎在其 iOS 照片应用程序的照片编辑中实现了这一点.(见下方截图)

我的尝试

我试图通过将 UIPanGestureRecognizer 附加到滚动视图并使用它的速度来获得这种行为.如果用户正在向吸附点拖动,滚动视图将禁用滚动,动画到吸附点,完成动画后将重新启用滚动.

然而,这会导致用户必须在拖动后抬起触摸并重新拖动滚动视图的问题.然而,苹果似乎在没有解除阻力的情况下做到了.

解决方案

我尝试模仿 iOS 照片应用.这是我的逻辑:

//计算捕捉点的内容偏移量让 snapPoint = CGPoint(x: 367, y: 0)//更改这些值以进行测试让 minDistanceToSnap = 7.0让 minVelocityToSnap = 25.0让 minDragDistanceToReleaseSnap = 7.0让 snapDuringDecelerating = false

这种滚动需要3个阶段

enum SnapState {案例将捕捉案例 didSnap案件将发布}

  1. willSnap: 默认状态.决定何时捕捉.比较 contentOffset 与 SnapPoint 的距离与 minDistanceToSnapscrollview 速度与 minVelocityToSnap.更改为 didSnap 状态.
  2. didSnap: 手动setContentOffset 到提供的contextOffset(snapPoint).在 scrollView 上计算 dragDistance.如果用户拖动超过一定距离 (minDragDistanceToReleaseSnap) 更改为 willRelease 状态.
  3. willRelease:如果距离snapPoint的滚动距离大于minDistanceToSnap,则再次更改为willSnap状态.立>


extension ViewController: UIScrollViewDelegate {func scrollViewDidScroll(scrollView: UIScrollView) {开关(快照状态){案例.willSnap:让 distanceFromSnapPoint = distance( between: scrollView.contentOffset, and: snapPoint)让速度 = scrollView.panGestureRecognizer.velocityInView(view)让速度距离 = 距离(之间:速度,和:CGPointZero)if distanceFromSnapPoint <= minDistanceToSnap &&速度距离 <= minVelocityToSnap &&(snapDuringDecelerating || velocityDistance > 0.0) {startSnapLocaion = scrollView.panGestureRecognizer.locationInView(scrollView)snapState = .didSnap}案例.didSnap:scrollView.setContentOffset(快照点,动画:假)变量拖动距离 = 0.0让位置 = scrollView.panGestureRecognizer.locationInView(scrollView)dragDistance = distance( between: location, and: startSnapLocaion)如果拖动距离 >minDragDistanceToReleaseSnap {startSnapLocaion = CGPointZerosnapState = .willRelease}案例.willRelease:让 distanceFromSnapPoint = distance( between: scrollView.contentOffset, and: snapPoint)如果 distanceFromSnapPoint >minDistanceToSnap {snapState = .willSnap}}}}

辅助函数

func distance(point1: CGPoint, and point2: CGPoint) ->双倍的 {return Double(hypotf(Float(point1.x - point2.x), Float(point1.y - point2.y)))}

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

注意:项目是用 Xcode 7.2 制作的.您可能需要稍作更改才能编译.

I am trying to figure out if I can use a UISnapBehavior from UIAnimator inside a UIScrollview to make scroll view's content snap to a point. So far my findings have been lead to that this is impossible.

What I am Trying to Achieve

UIScrollView to 'snap' to certain point while the user is dragging the scroll view. However, the scrolling has to resume from snapped position without the user having to lift the touch.

Apple seems to achieve this in Photo Editing in their iOS Photos App. (See screenshot below)

What I Tried

I tried to gain this behavior by attaching a UIPanGestureRecognizer to the scrollview and using it's velocity. If the user is dragging towards the snapping point, scroll view will disable scrolling, animate to the snapping point, when done animating it will re-enable scrolling.

However, this lead to the issue where the user HAS TO LIFT the touch up after the drag and re-drag the scrollview. Yet, Apple seems to have done it without having to lift the drag.

解决方案

I've tried to mimic iOS Photos app. Here is my logic:

// 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

This kind of scrolling needs 3 stages

enum SnapState {
case willSnap
case didSnap
case willRelease
}

  1. willSnap: Default state. Decide when to snap. Compare contentOffset distance from SnapPoint with minDistanceToSnap and scrollview velocity with minVelocityToSnap. Change to didSnap state.
  2. didSnap: Manually setContentOffset to a provided contextOffset(snapPoint). Calculate dragDistance on scrollView. If user drag more than a certain distance (minDragDistanceToReleaseSnap) change to willRelease state.
  3. willRelease: Change to willSnap state again if distance scroll from snapPoint is more than minDistanceToSnap.


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
                }
        }
    }
}

Helper function

func distance(between point1: CGPoint, and point2: CGPoint) -> Double {
    return Double(hypotf(Float(point1.x - point2.x), Float(point1.y - point2.y)))
}

Made a demo project on Github: https://github.com/rishi420/SnapDrag

Note: Project made with Xcode 7.2. You may need to change a bit to compile.

这篇关于UIAnimator 的 UISnapBehavior 可能与 UIScrollview 一起使用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆