![](/img/trans.png)
[英]Is it possible to snap UIViews using UISnapBehavior consecutively
[英]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
}
willSnap:
默認狀態。 確定何時捕捉。 比較contentOffset distance from SnapPoint with minDistanceToSnap
和scrollview velocity with minVelocityToSnap
。 更改為didSnap
狀態。 didSnap:
手動setContentOffset
到提供contextOffset(snapPoint)
在dragDistance
上計算scrollView
。 如果用戶拖動超過一定距離( minDragDistanceToReleaseSnap
), willRelease
改為willRelease
狀態。 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.