Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UINavigationBar滑开,而不是停留在原地_Ios_Swift_Uinavigationcontroller_Uinavigationbar - Fatal编程技术网

Ios UINavigationBar滑开,而不是停留在原地

Ios UINavigationBar滑开,而不是停留在原地,ios,swift,uinavigationcontroller,uinavigationbar,Ios,Swift,Uinavigationcontroller,Uinavigationbar,我创建了一个演示项目来展示这个问题 我们在UINavigationController中有两个视图控制器 MainViewController它是根目录 class MainViewController: UIViewController { lazy var button: UIButton = { let button = UIButton() button.setTitle("Detail", for: .normal) retur

我创建了一个演示项目来展示这个问题

我们在UINavigationController中有两个视图控制器

MainViewController
它是根目录

class MainViewController: UIViewController {

    lazy var button: UIButton = {
        let button = UIButton()
        button.setTitle("Detail", for: .normal)
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "Main"
        view.backgroundColor = .blue
        view.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        button.widthAnchor.constraint(equalToConstant: 150).isActive = true
        button.heightAnchor.constraint(equalToConstant: 42).isActive = true
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }

    @objc func buttonTapped(_ sender: UIButton) {
        navigationController?.pushViewController(DetailViewController(), animated: true)
    }
}
和推送的
DetailViewController

class DetailViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: animated)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.setNavigationBarHidden(false, animated: animated)
    }
}
如您所见,我想在
DetailViewController
中隐藏
UINavigationBar

问题


问题是,UINavigationBar滑开了,而不是和整个MainViewController呆在一起。如何更改该行为并保持弹出手势?

使用此post stackoverflow.com/a/5660278/7270113中的自定义推送转换。为了消除背部姿势(我理解这是您想要做的),只需关闭导航堆栈。您必须提供另一种退出
DetailViewController
的方法,因为即使您取消隐藏导航控制器,由于导航堆栈为空,Backfitten也将消失

@objc func buttonTapped(_ sender: UIButton) {

    let transition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionFade
    navigationController?.view.layer.add(transition, forKey: nil)

    let storyboard = UIStoryboard(name: "NameOfYourStoryBoard", bundle: .main)
    let viewController = storyboard.instantiateViewController(withIdentifier: "IdentifierOfDetailViewController") as! DetailViewController
    navigationController?.setViewControllers([viewController], animated: true) // This method will perform a push
}
从现在起,导航控制器将使用此过渡动画,如果要删除它,可以使用

navigationController?.view.layer.removeAllAnimations()
这可能就是你要找的

在开始推/弹出之前,启动导航栏隐藏/显示动画:

class MainViewController: UIViewController {

    lazy var button: UIButton = {
        let button = UIButton()
        button.setTitle("Detail", for: .normal)
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "Main"
        view.backgroundColor = .blue
        view.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        button.widthAnchor.constraint(equalToConstant: 150).isActive = true
        button.heightAnchor.constraint(equalToConstant: 42).isActive = true
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }

    @objc func buttonTapped(_ sender: UIButton) {
        navigationController?.setNavigationBarHidden(true, animated: true)
        navigationController?.pushViewController(DetailViewController(), animated: true)
    }
}

class DetailViewController: UIViewController {

    lazy var button: UIButton = {
        let button = UIButton()
        button.setTitle("Go Back", for: .normal)
        button.backgroundColor = .red
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        button.widthAnchor.constraint(equalToConstant: 150).isActive = true
        button.heightAnchor.constraint(equalToConstant: 42).isActive = true
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }

    @objc func buttonTapped(_ sender: UIButton) {
        navigationController?.setNavigationBarHidden(false, animated: true)
        navigationController?.popViewController(animated: true)
    }

}

MainViewController
中添加该方法

override func viewDidAppear(_ animated: Bool) {        
        UIView.animate(withDuration: 0) {
            self.navigationController?.setNavigationBarHidden(false, animated: false)
        }
    }
并在
DetailViewController


下面的代码是黑客攻击

override func viewDidAppear(_ animated: Bool) {        
    UIView.animate(withDuration: 0) {
        self.navigationController?.setNavigationBarHidden(false, animated: false)
    }
}
不要像@sagarbhut在(本线程中)中建议的那样编写这种奇怪的代码

你有两个选择

  • 不要黑客

  • 使用像这样的便利功能

    如果您使用的是故事板,请创建自定义序列。

    实施UIViewControlleranimated转换协议

    你可以取得一些好成绩,但恐怕你需要努力。网上有许多教程讨论如何实现上述功能


    推特的导航转换,推送的ViewController视图似乎占据了整个屏幕“隐藏导航栏”,但是,即使在过渡动画期间,仍然可以在推送ViewController中看到pop手势动画和导航栏,这显然无法通过设置栏的隐藏属性来实现

    实现自定义导航系统是实现这一点的一种方法,但我建议使用navigationBar的层及其zPosition属性来实现一个简单的解决方案。你需要两个步骤

    • 将navigationBar的layer zPosition设置为一个值,该值将放置在其同级项下,同级项包括导航堆栈中当前可见视图控制器的视图:
      navigationController?.navigationBar.layer.zPosition=-1

      推动VC的viewDidLoad可能是一个很好的地方

    • 既然navigationBar被放置在VC的视图后面,那么您需要调整视图的框架以确保它不会与navigationBar重叠(这会导致navigationBar被覆盖)。您可以使用viewWillLayoutSubviews更改视图的原点.y,以在navigationBar的楼层下开始(statusBarHeight+navigationBarHeight)
    那就行了。你不需要修改推送的VC,除非你想添加一个自定义后退按钮,如Twitter的个人资料屏幕。细节控制器的视图将位于导航栏的顶部,同时允许您保持弹出手势过渡。以下是使用此更改修改的示例代码:

    class MainViewController: UIViewController {
    
        lazy var button: UIButton = {
            let button = UIButton()
            button.setTitle("Detail", for: .normal)
            button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    
            return button
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            navigationItem.title = "Main"
            view.backgroundColor = .blue
    
            // Default value of layer's zPosition is 0 so setting it to -1 will place it behind its siblings.
            navigationController?.navigationBar.layer.zPosition = -1
    
            // The `view` will be under navigationBar so lets set a background color to the bar
            // as the view's backgroundColor to simulate the default behaviour.
            navigationController?.navigationBar.backgroundColor = view.backgroundColor
    
            // Hide the back button transition image.
            navigationController?.navigationBar.backIndicatorImage = UIImage()
            navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage()
    
            view.addSubview(button)
            addConstraints()
        }
    
        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
    
            // Place `view` under navigationBar.
            let statusBarPlusNavigationBarHeight: CGFloat = (navigationController?.navigationBar.bounds.height ?? 0) 
              + UIApplication.shared.statusBarFrame.height
            let viewHeight = UIScreen.main.bounds.height - statusBarPlusNavigationBarHeight
            view.frame = CGRect(origin: .zero, size: CGSize(width: view.bounds.width, height: viewHeight))
            view.frame.origin.y = statusBarPlusNavigationBarHeight
        }
    
        @objc func buttonTapped(_ sender: UIButton) {
            navigationController?.pushViewController(DetailViewController(), animated: true)
        }
    
        private func addConstraints() {
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
            button.widthAnchor.constraint(equalToConstant: 150).isActive = true
            button.heightAnchor.constraint(equalToConstant: 42).isActive = true
        }
    }
    
    class DetailViewController: UIViewController {
    
        // Some giant button to replace the navigationBar's back button item :)
        lazy var button: UIButton = {
            let b: UIButton = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: 80, height: 40)))
            b.frame.origin.y = UIApplication.shared.statusBarFrame.height
            b.backgroundColor = .darkGray
            b.setTitle("back", for: .normal)
            b.addTarget(self, action: #selector(DetailViewController.backButtonTapped), for: .touchUpInside)
            return b
        }()
    
        @objc func backButtonTapped() {
            navigationController?.popViewController(animated: true)
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .white
    
            view.addSubview(button)
        }
    }
    

    它是一个导航控制器堆栈,由
    navigationController
    管理。它与问题有何关系?这些信息将如何帮助我更改UINavigationBar的行为,它会滑走,而不是停留在MainViewController的位置上?是否希望在视图转换期间使NAVIGATIONBAR动画化?您可以尝试将其隐藏在
    viewdide
    中。。。这应该会给你动画效果,但它会在新视图滑动到位后出现。确切地说,它会一直保持到DetailViewController的动画结束,这很可怕。导航栏应该与下面的内容保持一致,我不知道为什么苹果开发者会将其更改为内容之外的幻灯片…@ThirdMartian我认为你应该创建一个自定义演示文稿。不,我认为是一样的!不是,像我写的那样尝试一下,你会得到你想要的东西不同类型的实例化视图控制器会有帮助吗?我说过几次,我想保持弹出手势。您的代码没有禁用它,但当您使用手势弹出时,导航栏会从左侧滑动,这不是我想要实现的。结果是UINavigationBar滑到顶部,并且在DetailViewController上可见一毫秒。看起来不太好。点击user.OK时查看Twitter应用程序-我会尝试查看Twitter应用程序(当前不使用),看看你想要什么效果。
    class MainViewController: UIViewController {
    
        lazy var button: UIButton = {
            let button = UIButton()
            button.setTitle("Detail", for: .normal)
            button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    
            return button
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            navigationItem.title = "Main"
            view.backgroundColor = .blue
    
            // Default value of layer's zPosition is 0 so setting it to -1 will place it behind its siblings.
            navigationController?.navigationBar.layer.zPosition = -1
    
            // The `view` will be under navigationBar so lets set a background color to the bar
            // as the view's backgroundColor to simulate the default behaviour.
            navigationController?.navigationBar.backgroundColor = view.backgroundColor
    
            // Hide the back button transition image.
            navigationController?.navigationBar.backIndicatorImage = UIImage()
            navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage()
    
            view.addSubview(button)
            addConstraints()
        }
    
        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
    
            // Place `view` under navigationBar.
            let statusBarPlusNavigationBarHeight: CGFloat = (navigationController?.navigationBar.bounds.height ?? 0) 
              + UIApplication.shared.statusBarFrame.height
            let viewHeight = UIScreen.main.bounds.height - statusBarPlusNavigationBarHeight
            view.frame = CGRect(origin: .zero, size: CGSize(width: view.bounds.width, height: viewHeight))
            view.frame.origin.y = statusBarPlusNavigationBarHeight
        }
    
        @objc func buttonTapped(_ sender: UIButton) {
            navigationController?.pushViewController(DetailViewController(), animated: true)
        }
    
        private func addConstraints() {
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
            button.widthAnchor.constraint(equalToConstant: 150).isActive = true
            button.heightAnchor.constraint(equalToConstant: 42).isActive = true
        }
    }
    
    class DetailViewController: UIViewController {
    
        // Some giant button to replace the navigationBar's back button item :)
        lazy var button: UIButton = {
            let b: UIButton = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: 80, height: 40)))
            b.frame.origin.y = UIApplication.shared.statusBarFrame.height
            b.backgroundColor = .darkGray
            b.setTitle("back", for: .normal)
            b.addTarget(self, action: #selector(DetailViewController.backButtonTapped), for: .touchUpInside)
            return b
        }()
    
        @objc func backButtonTapped() {
            navigationController?.popViewController(animated: true)
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .white
    
            view.addSubview(button)
        }
    }