在pageViewController内的tableView上滑动以删除

Gib*_*ley 9 tableview tableviewcell ios uipageviewcontroller swift

我有一个tableView内部,pageViewController当在一个单元格上滑动以显示删除单元格的选项时,只有在某些情况下才能识别出手势,比如说你快速而且积极地滑动.

我想这会发生,因为它不确定滑动手势是用于pageView还是用于tableView.有没有办法专门确定滑动手势发生的位置,以便能够顺利显示删除按钮?

Car*_*lin 6

我有同样的问题.我找到了一个运作良好的解决方案.

把它放在你UIPageViewControllerviewDidLoad功能中.

if let myView = view?.subviews.first as? UIScrollView {
    myView.canCancelContentTouches = false
}
Run Code Online (Sandbox Code Playgroud)

PageViewControllers有一个自动生成的子视图来处理手势.我们可以阻止这些子视图取消内容触摸.tableview将能够捕获删除按钮的滑动,同时仍然可以解释将tableview的手势要求作为页面滑动失败的滑动.如果您按住并轻扫或"猛烈地"滑动,则会显示删除按钮.


Sri*_*san 5

理论:

双方UIPageViewControllerUITableView实施使用UIScrollView,其中UIPageViewController嵌入功能UIScrollViewUITableView是的子类UIScrollView

UITableView还使用了几个UIPanGestureRecognizers来引入所有魔术。其中之一是UISwipeActionPanGestureRecognizer处理滑动以删除动作。

造成此问题的原因是,UIPageViewControllers UIPanGestureRecognizerUITableViews 冲突而胜出UISwipeActionPanGestureRecognizer

因此,UIPageViewController如果UITableViews UISwipeActionPanGestureRecognizer在起作用,我们必须知道如何忽略手势。

幸运的是UIGestureRecognizer

UIGestureRecognizerrequire(toFail otherGestureRecognizer: UIGestureRecognizer)创建两个手势识别器,以防止被称为手势的动作,直到其他手势识别失败之间的关系。

因此,所有我们必须做的是失败UIPageViewControllers的嵌入式UIScrollview小号panGestureRecognizerUITableView小号UISwipeActionPanGestureRecognizer被触发。

有两种方法可以实现此目的。

解决方案1:向表视图和Mimic添加新的手势识别器UISwipeActionPanGestureRecognizer。并使UIPageViewController panGesture要求使这个新的手势失败

解决方案2(有点脏):做一个字符串比较对UITableViewUISwipeActionPanGestureRecognizer,使UIPageViewControllerpanGesture需要失败这个新gestureRecognizer

码:

解决方案1 实用UIPageViewController的嵌入式工具UIScrollView

extension UIPageViewController {

    var scrollView: UIScrollView? {
        return view.subviews.first { $0 is UIScrollView } as? UIScrollView
    }

}
Run Code Online (Sandbox Code Playgroud)

将以下代码添加到中UIViewControllerUITableView并从中调用viewDidLoad()

func handleSwipeDelete() {
    if let pageController = parent?.parent as? UIPageViewController {
        let gestureRecognizer = UIPanGestureRecognizer(target: self, action: nil)
        gestureRecognizer.delaysTouchesBegan = true
        gestureRecognizer.cancelsTouchesInView = false
        gestureRecognizer.delegate = self
        tableView.addGestureRecognizer(gestureRecognizer)

        pageController.scrollView?.canCancelContentTouches = false
        pageController.scrollView?.panGestureRecognizer.require(toFail: gestureRecognizer)
    }
}
Run Code Online (Sandbox Code Playgroud)

最后委托方法

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    guard let panGesture = gestureRecognizer as? UIPanGestureRecognizer else {
        return false
    }

    let translation = panGesture.translation(in: tableView)
    // In my case I have only trailing actions, so I used below condition.
    return translation.x < 0
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                       shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return otherGestureRecognizer.view == tableView
}
Run Code Online (Sandbox Code Playgroud)

解决方案2(有点脏) 一个有用的实用程序,可以将其UIPageViewController嵌入UIScrollView

extension UIPageViewController {

    var scrollView: UIScrollView? {
        return view.subviews.first { $0 is UIScrollView } as? UIScrollView
    }

}
Run Code Online (Sandbox Code Playgroud)

将以下代码添加到中UIViewControllerUITableView并从中调用viewDidLoad()

func handleSwipeDelete() {
    guard let pageController = parent as? UIPageViewController else {
        return
    }

    pageController.scrollView?.canCancelContentTouches = false
    tableView.gestureRecognizers?.forEach { recognizer in
        let name = String(describing: type(of: recognizer))
        guard name == "_UISwipeActionPanGestureRecognizer" else {
            return
        }
        pageController.scrollView?
            .panGestureRecognizer
            .require(toFail: recognizer)
    }
}
Run Code Online (Sandbox Code Playgroud)