默认情况下,如果从屏幕的左边缘向右拖动,它将拖走ViewController并将其从堆栈中取出。
我想将此功能扩展到整个屏幕。当用户在任何地方拖动时,我也希望发生同样的事情。
我知道我可以实现向右滑动手势,只需拨打<% if %>
<% else %>
<% end %>
然而,没有&#34;拖动&#34;运动。我希望用户能够右键拖动视图控制器,就好像它是一个对象,揭示了它下面的内容。并且,如果它被拖过50%,则将其解雇。 (查看Instagram以了解我的意思。)
答案 0 :(得分:26)
在Github制作了一个演示项目https://github.com/rishi420/SwipeRightToPopController
我已使用UIViewControllerAnimatedTransitioning
协议
来自doc:
//这用于百分比驱动的交互式转换,以及容器控制器......
在控制器的视图中添加了UIPanGestureRecognizer
。这是手势的动作:
func handlePanGesture(panGesture: UIPanGestureRecognizer) {
let percent = max(panGesture.translationInView(view).x, 0) / view.frame.width
switch panGesture.state {
case .Began:
navigationController?.delegate = self
navigationController?.popViewControllerAnimated(true)
case .Changed:
percentDrivenInteractiveTransition.updateInteractiveTransition(percent)
case .Ended:
let velocity = panGesture.velocityInView(view).x
// Continue if drag more than 50% of screen width or velocity is higher than 1000
if percent > 0.5 || velocity > 1000 {
percentDrivenInteractiveTransition.finishInteractiveTransition()
} else {
percentDrivenInteractiveTransition.cancelInteractiveTransition()
}
case .Cancelled, .Failed:
percentDrivenInteractiveTransition.cancelInteractiveTransition()
default:
break
}
}
步骤:
.Begin:
指定要执行的segue并指定UINavigationController
委托。 InteractiveTransitioning
.Changed:
UpdateInteractiveTransition with percentage .Ended:
如果拖动50%或更高或更高速度,则继续保持转换.Cancelled, .Failed:
取消转换
参考文献:
答案 1 :(得分:3)
@Warif Akhand Rishi接受的答案的Swift 4版本
即使此答案确实有效,我还是发现了2个怪癖。
除此之外,它肯定可以正常工作,您可以左右滑动以将其关闭。
class ViewController: UIGestureRecognizerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.delegate = self
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
view.addGestureRecognizer(panGesture)
}
@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer){
let interactiveTransition = UIPercentDrivenInteractiveTransition()
let percent = max(gesture.translation(in: view).x, 0) / view.frame.width
switch gesture.state {
case .began:
navigationController?.delegate = self
navigationController?.popViewController(animated: true)
case .changed:
interactiveTransition.update(percent)
case .ended:
let velocity = gesture.velocity(in: view).x
// Continue if drag more than 50% of screen width or velocity is higher than 1000
if percent > 0.5 || velocity > 1000 {
interactiveTransition.finish()
} else {
interactiveTransition.cancel()
}
case .cancelled, .failed:
interactiveTransition.cancel()
default:break
}
}
}
答案 2 :(得分:2)
答案 3 :(得分:2)
创建一个平移手势识别器,并在其中移动交互式弹出手势识别器的目标。
将您的识别器添加到推送的视图控制器的viewDidLoad中,瞧!
let popGestureRecognizer = self.navigationController!.interactivePopGestureRecognizer!
if let targets = popGestureRecognizer.value(forKey: "targets") as? NSMutableArray {
let gestureRecognizer = UIPanGestureRecognizer()
gestureRecognizer.setValue(targets, forKey: "targets")
self.view.addGestureRecognizer(gestureRecognizer)
}
答案 4 :(得分:0)
向右轻扫以关闭视图控制器
Swift 5版本- (从右向左滑动时也删除了手势识别)
重要- 在VC2的“属性检查器”中,将“演示文稿”值从“全屏”设置为“全屏”。这样一来,在通过手势关闭VC2时,可以看到VC1。如果没有手势,VC2后面会出现黑屏,而不是VC1。
class ViewController: UIGestureRecognizerDelegate, UINavigationControllerDelegate {
var initialTouchPoint: CGPoint = CGPoint(x: 0, y: 0)
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.delegate = self
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
view.addGestureRecognizer(panGesture)
}
@objc func handlePanGesture(_ sender: UIPanGestureRecognizer) {
let touchPoint = sender.location(in: self.view?.window)
let percent = max(sender.translation(in: view).x, 0) / view.frame.width
let velocity = sender.velocity(in: view).x
if sender.state == UIGestureRecognizer.State.began {
initialTouchPoint = touchPoint
} else if sender.state == UIGestureRecognizer.State.changed {
if touchPoint.x - initialTouchPoint.x > 0 {
self.view.frame = CGRect(x: touchPoint.x - initialTouchPoint.x, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
}
} else if sender.state == UIGestureRecognizer.State.ended || sender.state == UIGestureRecognizer.State.cancelled {
if percent > 0.5 || velocity > 1000 {
navigationController?.popViewController(animated: true)
} else {
UIView.animate(withDuration: 0.3, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
})
}
}
}
}
希望这会有所帮助。 如有必要,随时提出更改建议。
答案 5 :(得分:0)
我认为这比建议的解决方案容易,并且也适用于该导航内的所有viewController以及嵌套的滚动视图。
https://stackoverflow.com/a/58779146/8517882
只需安装吊舱,然后使用EZNavigationController
而不是UINavigationController
来使该导航控制器内的所有视图控制器具有此行为。
答案 6 :(得分:-3)
您可以使用滑动右手势来实现此目的:
override func viewDidLoad() {
super.viewDidLoad()
var swipeRight = UISwipeGestureRecognizer(target: self, action: "popViewController:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
}
func popViewController(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
self.navigationController.popViewControllerAnimated(true)
default:
break
}
}
}