在视图控制器之间平移(而不是滑动)

Pan (not swipe) between view controllers

我正在创建一个用户界面类似于 Tinder 的应用程序。

我的意思是,可以在三个主视图控制器之间 "panned"。用户只需拖动即可移动到三个视图控制器中的任何一个。

我在我的应用程序中实现了类似的功能,但有一个重要警告:它使用 swipe 手势识别器,而不是 pan 手势识别器。

最终结果看起来和感觉起来都非常不自然。

这就是我希望我的用户界面的行为方式(忽略 Gecko):

这是它当前与滑动手势识别器的行为方式:

注意如何使用 Tinder,您可以平移到新的视图控制器而无需完全提交 segue。而且,如果平移没有将当前视图控制器移动到超过最小阈值,它会简单地弹回原位。这就是我要寻找的行为。

这是我目前用来模仿滑动手势识别器的一些代码:

//The following logic is applied in a similar way to view controllers 1 and 3 as well.

class ViewController2: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        addSwipeGestureRecognizers()
    }

    func addSwipeGestureRecognizers() {
        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeLeft))
        swipeLeft.direction = UISwipeGestureRecognizer.Direction.left
        self.view.addGestureRecognizer(swipeLeft)

        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeRight))
        swipeRight.direction = UISwipeGestureRecognizer.Direction.right
        self.view.addGestureRecognizer(swipeRight)
    }

    @objc func handleSwipeLeft() {
        let storyboard = UIStoryboard(name: "Main", bundle: .main)
        let viewController1 = storyboard.instantiateViewController(withIdentifier: "ViewController1") as! ViewController1
        let transition:CATransition = CATransition()
        transition.duration = 0.25
        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        transition.type = CATransitionType.push
        transition.subtype = CATransitionSubtype.fromLeft
        self.navigationController!.view.layer.add(transition, forKey: kCATransition)
        navigationController!.pushViewController(viewController1, animated: false)
    }

    @objc func handleSwipeRight() {
        let storyboard = UIStoryboard(name: "Main", bundle: .main)
        let viewController3 = storyboard.instantiateViewController(withIdentifier: "ViewController3") as! ViewController3
        let transition:CATransition = CATransition()
        transition.duration = 0.25
        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        transition.type = CATransitionType.push
        transition.subtype = CATransitionSubtype.fromRight
        self.navigationController!.view.layer.add(transition, forKey: kCATransition)
        navigationController!.pushViewController(viewController3, animated: false)
    }
}

我还利用自定义 UIViewControllerAnimatedTransitioning 使推送视图控制器从左侧或右侧推出呈现视图控制器。这样做与呈现视图控制器顶部的默认堆叠相反。我还隐藏了 UINavigationController 的导航栏。

我不确定 UINavigationController 是否是提供您所需内容的正确容器控制器。您可能会发现 UIPageViewController 是一个更好的选择,我认为它会提供您正在寻找的开箱即用的自然滑动手势,尽管它是一个相当不透明 class 并且有其自身的一些怪癖。

要走自定义路线(使用 UINavigationController 或更多 flexible/customisable UIViewController 自定义演示),您使用 UIViewControllerAnimatedTransitioning 和其他(许多)相关协议走在正确的轨道上。如果您赶时间,那条路线将花费您相当长的时间来实现,因此目前可能需要一个简单的 UIPageViewController 实现。

github 上的这个项目可能会帮助您实现您的要求 - Here