如何在Xcode 9、Swift 4中创建同时滑入淡入的自定义Segue
嘿,我来帮你搞定这个自定义Segue的问题!其实你不用纠结直接引用leading/trailing约束,自定义转场动画更常用的方式是直接修改视图的位置和透明度,就能实现你要的“右侧滑入+淡入”、“右侧滑出+淡出”效果。下面是具体的实现步骤:
实现带淡入淡出的左右滑动自定义Segue
1. 先写自定义Segue的核心代码
新建一个继承自UIStoryboardSegue的类,比如叫SlideFadePushSegue,代码如下:
import UIKit class SlideFadePushSegue: UIStoryboardSegue { override func perform() { // 拿到源控制器和目标控制器的视图 guard let sourceView = source.view, let destView = destination.view else { super.perform() return } // 设置目标视图的初始状态:在屏幕右侧外,完全透明 destView.frame = CGRect(x: sourceView.bounds.width, y: 0, width: sourceView.bounds.width, height: sourceView.bounds.height) destView.alpha = 0.0 // 把目标视图加到窗口层级里,放在源视图上面 sourceView.window?.insertSubview(destView, aboveSubview: sourceView) // 执行动画 UIView.animate(withDuration: 0.3, animations: { // 目标视图滑入屏幕,同时淡入 destView.frame = sourceView.bounds destView.alpha = 1.0 // 可选:让源视图稍微左移一点,更贴近系统Push的视觉感 sourceView.frame = CGRect(x: -sourceView.bounds.width * 0.1, y: 0, width: sourceView.bounds.width, height: sourceView.bounds.height) }) { _ in // 动画结束后,完成导航跳转(如果是模态跳转就用present) self.source.navigationController?.pushViewController(self.destination, animated: false) } } }
2. 处理返回(Pop)的动画效果
如果要在返回时也有对应的滑出+淡出,你可以在目标控制器里自定义返回动作,比如给返回按钮加个点击事件:
@IBAction func backButtonTapped(_ sender: UIButton) { guard let nav = navigationController, let sourceView = nav.viewControllers[nav.viewControllers.count - 2].view else { navigationController?.popViewController(animated: false) return } UIView.animate(withDuration: 0.3, animations: { // 当前视图滑出屏幕右侧,同时淡出 self.view.frame = CGRect(x: sourceView.bounds.width, y: 0, width: sourceView.bounds.width, height: sourceView.bounds.height) self.view.alpha = 0.0 // 源视图回到原始位置 sourceView.frame = sourceView.bounds }) { _ in self.navigationController?.popViewController(animated: false) } }
3. 额外提示
- 如果是模态跳转(不是导航栏Push),把代码里的
pushViewController换成present,返回时用dismiss就行。 - 动画时长可以自己调,系统默认的Push动画大概是0.3秒,这个数值比较自然。
- 如果你想做更复杂的转场(比如支持侧滑返回),可以用
UINavigationControllerDelegate结合UIViewControllerAnimatedTransitioning来实现,这种方式比单纯的自定义Segue更灵活。
至于你之前想的leading/trailing约束,其实在这种全屏转场场景下没必要用——当然也可以通过修改约束来实现,比如给目标视图加leading约束到父视图的trailing,动画时把约束constant改成0再调用layoutIfNeeded(),但直接改frame会更简单直接~
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

