mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
116 lines
3.8 KiB
Swift
116 lines
3.8 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import UIKit.UIGestureRecognizerSubclass
|
|
|
|
private func traceScrollView(view: UIView, point: CGPoint) -> UIScrollView? {
|
|
for subview in view.subviews {
|
|
let subviewPoint = view.convert(point, to: subview)
|
|
if subview.frame.contains(point), let result = traceScrollView(view: subview, point: subviewPoint) {
|
|
return result
|
|
}
|
|
}
|
|
if let scrollView = view as? UIScrollView {
|
|
return scrollView
|
|
}
|
|
return nil
|
|
}
|
|
|
|
private final class InternalGestureRecognizerDelegate: NSObject, UIGestureRecognizerDelegate {
|
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
return true
|
|
}
|
|
|
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
if otherGestureRecognizer is UIPanGestureRecognizer {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
public class SwipeToDismissGestureRecognizer: UIGestureRecognizer, UIGestureRecognizerDelegate {
|
|
private let internalDelegate = InternalGestureRecognizerDelegate()
|
|
|
|
private var beginPosition = CGPoint()
|
|
|
|
override public init(target: Any?, action: Selector?) {
|
|
super.init(target: target, action: action)
|
|
|
|
self.delegate = self.internalDelegate
|
|
}
|
|
|
|
override public func reset() {
|
|
super.reset()
|
|
|
|
self.state = .possible
|
|
}
|
|
|
|
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
|
|
super.touchesBegan(touches, with: event)
|
|
|
|
guard let touch = touches.first, let view = self.view else {
|
|
self.state = .failed
|
|
return
|
|
}
|
|
|
|
var found = false
|
|
let point = touch.location(in: self.view)
|
|
if let scrollView = traceScrollView(view: view, point: point) {
|
|
let contentOffset = scrollView.contentOffset
|
|
let contentInset = scrollView.contentInset
|
|
if contentOffset.y.isLessThanOrEqualTo(contentInset.top) {
|
|
found = true
|
|
}
|
|
}
|
|
if found {
|
|
self.beginPosition = point
|
|
} else {
|
|
self.state = .failed
|
|
}
|
|
}
|
|
|
|
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
|
|
super.touchesMoved(touches, with: event)
|
|
|
|
guard let touch = touches.first, let view = self.view else {
|
|
self.state = .failed
|
|
return
|
|
}
|
|
|
|
let point = touch.location(in: self.view)
|
|
|
|
let translation = CGPoint(x: point.x - self.beginPosition.x, y: point.y - self.beginPosition.y)
|
|
|
|
if self.state == .possible {
|
|
if abs(translation.x) > 5.0 {
|
|
self.state = .failed
|
|
return
|
|
}
|
|
var lockDown = false
|
|
let point = touch.location(in: self.view)
|
|
if let scrollView = traceScrollView(view: view, point: point) {
|
|
let contentOffset = scrollView.contentOffset
|
|
let contentInset = scrollView.contentInset
|
|
if contentOffset.y.isLessThanOrEqualTo(contentInset.top) {
|
|
lockDown = true
|
|
}
|
|
}
|
|
if lockDown {
|
|
if translation.y > 2.0 {
|
|
self.state = .began
|
|
}
|
|
} else {
|
|
self.state = .failed
|
|
}
|
|
} else {
|
|
self.state = .changed
|
|
}
|
|
}
|
|
|
|
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
|
|
super.touchesEnded(touches, with: event)
|
|
|
|
self.state = .failed
|
|
}
|
|
}
|