簡體   English   中英

UIAnimator的UISnapBehavior是否可以與UIScrollview一起使用?

[英]UIAnimator's UISnapBehavior possible with UIScrollview?

我試圖找出是否可以在UIScrollview內使用UIAnimator中的UISnapBehavior來使滾動視圖的內容對齊到一個點。 到目前為止,我的發現導致這是不可能的。

我正在努力實現的目標

當用戶拖動滾動視圖時,UIScrollView會“捕捉”到特定點。 然而,滾動必須從捕捉位置恢復,而用戶不必抬起觸摸。

蘋果似乎在其iOS Photos App中通過Photo Editing實現了這一目標。 (請參見下面的屏幕截圖)

在此處輸入圖片說明

我嘗試過的

我試圖通過將UIPanGestureRecognizer附加到滾動視圖並使用其速度來獲得此行為。 如果用戶向着捕捉點拖動,則滾動視圖將禁用滾動,以動畫形式捕捉到捕捉點,完成動畫后將重新啟用滾動。

但是,這導致了以下問題:在拖動並重新拖動滾動視圖后,用戶必須抬起修飾框。 然而,蘋果似乎已經做到了這一點,而無需解除阻力。

我試圖模仿iOS Photos應用。 這是我的邏輯:

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

這種滾動需要三個階段

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改為willRelease狀態。
  3. willRelease:如果distance scroll from snapPoint大於minDistanceToSnap則再次更改為willSnap狀態。


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

輔助功能

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創建的項目。 您可能需要稍作改動才能進行編譯。

不要將UIPanGestureRecognizer直接添加到UIScrollView中。 而是將其添加到容器視圖中,然后在選擇器中手動設置UIScrollView contentOffset。

禁用UIScrollView本身的交互,或使用委托,以防止直接與滾動視圖交互。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM