禁用手势下拉表单/页面模态呈现

124
在iOS 13中,使用表单和页面样式的模态呈现可以通过向下拖动手势来解除。在我的某个表单中,这是有问题的,因为用户会在此框中绘制图案,这会干扰手势。它会将屏幕拉下来,而不是画出垂直线。
如何禁用以表单形式呈现的模态视图控制器中的垂直滑动关闭手势?
设置 isModalInPresentation = true仍然允许下拉该sheet,只是不会关闭。

2
在Apple Developer上有一份详细说明文档:https://developer.apple.com/documentation/uikit/view_controllers/disabling_pulling_down_a_sheet - Stleamist
3
但是他们没有解释如何处理当该手势干扰其他人时,就像这个问题所问的那样。 - teradyl
17个回答

1

Me, I use this :

-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];

for(UIGestureRecognizer *gr in self.presentationController.presentedView.gestureRecognizers) {
    if (@available(iOS 11.0, *)) {
        if([gr.name isEqualToString:@"_UISheetInteractionBackgroundDismissRecognizer"]) {
            gr.enabled = false;
        }
    }
}

0

iOS 15 以后的 SwiftUI

    .interactiveDismissDisabled()

例如:

    .sheet(isPresented: $add) {
        AddView()
            .interactiveDismissDisabled()
    }

0
UITableViewUICollectionView 启动页面表单取消手势时,如果用户尝试向上滚动滚动视图的顶端,则可以通过添加一个调用 endRefreshing 的不可见 UIRefreshControl 来禁用此手势。
另请参见 https://dev59.com/OD4DtIcB2Jgan1zn983H#58676756

0

将尝试更详细地描述@Jordan H已经建议的第二种方法:

1)为了能够捕获并决定有关模态表单的手势移动,请将以下内容添加到视图控制器的viewDidLoad中:

navigationController?.presentationController?.presentedView?.gestureRecognizers?.forEach {
   $0.delegate = self
}

2)使用gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:),使得能够同时捕捉到平移手势和自定义手势的能力。
3)实际的决策可以放在gestureRecognizer(_:shouldBeRequiredToFailBy:)中。
示例代码,如果同时存在滑动手势和面板的平移手势,则优先选择滑动手势。这不会影响没有滑动手势识别器的区域中的原始平移手势,因此原始的“滑动关闭”仍然可以按设计工作。
extension PeopleViewController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer === UIPanGestureRecognizer.self && otherGestureRecognizer === UISwipeGestureRecognizer.self {
            return true
        }
        return false
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

在我的情况下,我只有几个滑动手势识别器,因此比较类型对我来说已经足够了,但如果有更多的手势识别器,将手势识别器本身进行比较可能是有意义的(无论是以编程方式添加的还是作为接口生成器的输出),如此文档所述:https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/coordinating_multiple_gesture_recognizers/preferring_one_gesture_over_another

以下是代码在我的情况下的工作原理。没有它,滑动手势大多被忽略,只偶尔起作用。

enter image description here


嘿,我尝试了你的解决方案,但我仍然有一个问题。当我在viewDidAppear中设置委托时(因为我的presentationController为空,我只是道德上呈现一个vc)。然后,我迭代其视图的监督以查找视图是否具有PanGesture,并将其委托设置为self。然后我的vc无法向下滑动以解除,是否有其他方法来解决我的问题?请帮忙。 - Weslie
@Weslie,你需要捕获所呈现视图的识别器,而不是其父视图的识别器。尝试暂时添加gestureRecognizerShouldBegin委托方法,以查看实际捕获的手势并进行调试。 - Vitalii

-1
iOS禁用模态视图控制器的手势识别器
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    //if you use UINavigationController
    self.navigationController?.presentationController?.presentedView?.gestureRecognizers?.forEach {
        $0.isEnabled = false
    }

    //if not
    self.presentationController?.presentedView?.gestureRecognizers?.forEach {
        $0.isEnabled = false
    }
}

presentedView 返回的不是 viewController.view 对象

//po navigationController?.presentationController?.presentedView
<UIDropShadowView: 0x10bd69100; frame = (0 57; 390 787); gestureRecognizers = <NSArray: 0x2821d26d0>; layer = <CALayer: 0x282f0c7c0>>

//po self.view
<UIView: 0x10bd67c90; frame = (0 0; 390 787); autoresize = W+H; backgroundColor = <UIDynamicSystemColor: 0x283ada180; name = systemBackgroundColor>; layer = <CALayer: 0x282f0ca40>>

-3

在 prepare(for:sender:) 中:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == viewControllerSegueID {
        let controller = segue.destination as! YourViewController
        controller.modalPresentationStyle = .fullScreen
    }
}

或者,在您初始化控制器之后:

let controller = YourViewController()
controller.modalPresentationStyle = .fullScreen

-3

对于导航控制器,为了避免滑动手势与弹出视图的交互,我们可以使用:

if #available(iOS 13.0, *) {navController.isModalInPresentation = true}

2
不是的,但这并不妨碍“手势”,这也是问题所在。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接