【问题标题】:animate subviews inside UINavigationBar when pushing to detailviewController推送到 detailviewController 时为 UINavigationBar 内的子视图设置动画
【发布时间】:2020-02-14 12:23:55
【问题描述】:

我的导航栏中有一些子视图。一个黑色方块,一些标题和一个蓝色条。当推送到详细视图控制器时,我希望我的子视图隐藏(动画)。 我将地铁添加到主视图控制器内的导航栏中,使用 self.navigationController?.navigationBar.addsubView(mySubview).

目前,它看起来像他的:

在细节视图控制器中隐藏(动画)这些子视图的正确方法是什么?

【问题讨论】:

    标签: ios uiviewcontroller uinavigationbar uiviewanimation


    【解决方案1】:

    你的问题很有趣。我从没想过导航栏。

    UINavigationController用作根控制器时,所有UIViewControllers都存储在其堆栈中,这意味着所有UIViewControllers共享一个navigationBar。 您在第一个UIViewController 中将mySubView 添加到navigationBar。如果想在详情页隐藏,可以直接搜索子视图。

    第一步,需要给mySubView一个标签,可以是标签,也可以是自定义类型,方便后面判断。

    在第一页

       import SnapKit 
    
       mySubView = UIView()
       mySubView?.tag = 999
       mySubView?.backgroundColor = .red
       mySubView?.translatesAutoresizingMaskIntoConstraints = false
    
       let navBar = navigationController?.navigationBar
       navBar!.addSubview(mySubView!)
    
       mySubView!.snp.makeConstraints { (make) in
           make.left.equalTo(navBar!).offset(100)
           make.centerY.equalTo(navBar!)
           make.width.height.equalTo(50)
       }
    

    在详细信息页面上,我删除了isHidden,并用属性保存了navigationBar,因为在手势过程中navigationBar = nil。如果SnapKit 不熟悉,请多花几分钟时间学习。

       var mySubView: UIView? = nil
       var navBar: UINavigationBar?
    
       override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .white
            // Do any additional setup after loading the view.
    
        navigationController?.interactivePopGestureRecognizer?.addTarget(self, action: #selector(backGesture))
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            homeNavigationBarStatus()
        }
    
        override func viewDidDisappear(_ animated: Bool) {
            super.viewDidDisappear(animated)
            homeNavigationBarStatus()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            if mySubView == nil {
                for view: UIView in (navigationController?.navigationBar.subviews)! {
                    if view.tag == 999 {
                        mySubView = view
                    }
                }
            }
    
            UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut, animations: {
                self.detailNavigationBarStatus()
            }, completion: nil)
        }
    
        func detailNavigationBarStatus(){
            changingNavigationBarStatus(progress: 0)
        }
    
        func homeNavigationBarStatus(){
            changingNavigationBarStatus(progress: 1.0)
        }
    
        func changingNavigationBarStatus(progress:CGFloat){
            mySubView?.alpha = progress
            mySubView?.snp.updateConstraints({ (make) in
               make.left.equalTo(navBar!).offset(100 * progress)
            })
        }
    
        @objc func backGesture(sender: UIScreenEdgePanGestureRecognizer) {
            switch sender.state {
                case .changed:
                    let x = sender.translation(in: view).x
                    progress =  x / view.frame.width
                    changingNavigationBarStatus(progress: progress)
    
                default:
                    break
            }
        }
    

    但是使用标签值不够优雅,可以为mySubView创建一个具体的类,也可以通过类来判断。

    【讨论】:

    • 有没有办法让这个互动?例如,当您从屏幕左边缘向右滑动时,我希望动画依赖于 iOS 中的向后滑动手势
    • 可以,navigationController?.interactivePopGestureRecognizer可以,已更新
    • 如果我使用更新答案的代码,如果我使用 edgePanGesture,子视图只会再次淡入。如果我点击后退按钮,子视图将不会再次淡入。它将保持隐藏状态。需要明确的是:第一个解决方案有效,这个解决方案有效。但也许您应该更新答案以支持这两种模式:交互式返回上一个屏幕并点击返回按钮
    • 对不起,我不小心删除了,现在我添加了。
    • 有没有办法为这些子视图的约束设置动画?我希望我的子视图向左淡出屏幕。所有这些子视图都使用主视图控制器中的自动布局来调整大小和位置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多