仅在 UIPageViewController 上的某个方向上禁用用户滑动?

Posted

技术标签:

【中文标题】仅在 UIPageViewController 上的某个方向上禁用用户滑动?【英文标题】:Disabling User Swipes only in certain direction on UIPageViewController? 【发布时间】:2018-10-04 20:42:40 【问题描述】:

我遇到了嵌入在 UIPageViewController 中的 UITableviewController 的问题……系统无法区分向左滑动以更改页面和滑动以删除 UITableView 中的项目。这个特殊的 UITableViewController 恰好在 PageViewController 的最后一页上,所以由于向左滑动并没有真正做任何事情(向右没有任何作用),我可以在当前页面 == 3 时禁用 PageViewController 检测滑动。棘手的部分是我只有想要忽略向左滑动(以便 tableView 将左侧滑动读取为要删除的滑动),而我仍想检测向右滑动以便用户可以导航回第 2 页。

UIPageViewController 代码:

class WorkoutPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource 


    //var pageControl = UIPageControl()
    var referenceToNewWorkoutKingVC: NewWorkoutKingViewController?


    // MARK: UIPageViewControllerDataSource

    lazy var orderedViewControllers: [UIViewController] = 

        var viewControllers = [UIViewController]()

        if referenceToNewWorkoutKingVC?.sessionType == goalieSessionString || referenceToNewWorkoutKingVC?.sessionType == refSessionString || referenceToNewWorkoutKingVC?.sessionType == coachSessionString || referenceToNewWorkoutKingVC?.sessionType == openSkateSessionString 

            viewControllers = [self.newVc(viewController: "NewIceDataTableViewController"),
                               self.newVc(viewController: "NewHealthDataTableViewController")]

         else 
            viewControllers = [self.newVc(viewController: "NewIceDataTableViewController"),
                               self.newVc(viewController: "NewHealthDataTableViewController"),
                               self.newVc(viewController: "NewShiftTableViewController")]

        


       return viewControllers
    ()

     let impact = UIImpactFeedbackGenerator(style: UIImpactFeedbackGenerator.FeedbackStyle.medium)

    override func viewDidLoad() 
        super.viewDidLoad()
        self.dataSource = self
        self.delegate = self


        // This sets up the first view that will show up on our page control
        if let firstViewController = orderedViewControllers.first 
            setViewControllers([firstViewController],
                               direction: .forward,
                               animated: true,
                               completion: nil)
        

    



    func newVc(viewController: String) -> UIViewController 
        return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: viewController)
    




    // MARK: Delegate methods
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 
        let pageContentViewController = pageViewController.viewControllers![0]
        referenceToNewWorkoutKingVC?.pageControl.numberOfPages = orderedViewControllers.count
        referenceToNewWorkoutKingVC?.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!


    

    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) 
        //Haptic when pages switch, code from: https://www.hackingwithswift.com/example-code/uikit/how-to-generate-haptic-feedback-with-uifeedbackgenerator
        impact.prepare()
        impact.impactOccurred()
    

    // MARK: Data source functions.
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? 
        guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else 
            return nil
        

        let previousIndex = viewControllerIndex - 1

        // User is on the first view controller and swiped left to loop to
        // the last view controller.
        guard previousIndex >= 0 else 
            //return orderedViewControllers.last
            // Uncommment the line below, remove the line above if you don't want the page control to loop.
            return nil
        

        guard orderedViewControllers.count > previousIndex else 
            return nil
        

        return orderedViewControllers[previousIndex]
    

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? 
        guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else 
            return nil
        

        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = orderedViewControllers.count

        // User is on the last view controller and swiped right to loop to
        // the first view controller.
        guard orderedViewControllersCount != nextIndex else 
            //return orderedViewControllers.first
            // Uncomment the line below, remove the line above if you don't want the page control to loop.
            return nil
        

        guard orderedViewControllersCount > nextIndex else 
            return nil
        

        return orderedViewControllers[nextIndex]
    


【问题讨论】:

尝试将bounces属性禁用到falseUIPageViewController子视图UIScrollView 如果您的列表在最后一页,它应该可以正常工作,只需检查/验证滑动以删除代码是否到位并且可以正常工作 【参考方案1】:

试试这个

func managePageControllerBounces(isEnable : Bool) 

    for view in pageViewController.view.subviews 
    
        if view is UIScrollView 
            let scrollView = view as? UIScrollView
            scrollView?.bounces = isEnable
        
    

根据要求切换退回

self.manegePageControllerBounces(isEnable: false)

希望对你有所帮助....

【讨论】:

谢谢!这确实有点帮助,弹跳的减少使得滑动删除变得更容易一些,但它仍然有点困难并且需要多次尝试。我还能做些什么来让滑动删除更容易吗?感觉好像tableView的cell里面的手势识别器太小了 是的,我添加了这样您就可以看到何时触发了删除操作。

以上是关于仅在 UIPageViewController 上的某个方向上禁用用户滑动?的主要内容,如果未能解决你的问题,请参考以下文章

带有 Aspect Fill 图像模式的奇怪 UIPageViewController 滑动行为

UIPageViewController 让 UItalkeViewController 在 iOS 13 上“跳跃”

viewWillAppear 没有在 UIPageViewController 孩子上被调用

如何在 UIPageViewController 上禁用多点触控?

UIPageViewController 将先前的 ViewController 保持在视图的背景上

带有上一个和下一个按钮的 UIPageViewController