将子图层添加到导航栏与转换冲突

时间:2016-07-26 05:11:05

标签: ios uinavigationcontroller uinavigationbar core-animation calayer

我需要在UIInavigationBar下面添加一个边框,我也希望它是全局的,所以我转到我的顶级层次结构UIViewController并在其中放置一个与此类似的方法:

- (void)setupNavigationBarBorder {
    if (![self isKindOfClass:[CombinedViewController class]]) {
        CGRect borderRect = CGRectMake(0, self.navigationController.navigationBar.frame.size.height-0.5f, self.navigationController.navigationBar.frame.size.width, 0.5f);
        CALayer *border = [CALayer layer];
        border.frame = borderRect;
        border.name = @"border";
        [border setBackgroundColor:[UIColor greenColor].CGColor];
        [self.navigationController.navigationBar.layer addSublayer:border];
    } else {
        NSArray* sublayers = [NSArray arrayWithArray:self.navigationController.navigationBar.layer.sublayers];
        for (CALayer *layer in sublayers) {
            if ([layer.name isEqualToString:@"border"]) {
                [layer removeFromSuperlayer];
            }
        }
    }
}

这是一个简单的触发器,用于绘制和删除此子图层。非常直截了当。所以起初我已经决定将这段代码放在viewDidLoad中,但结果证明这不是最好的主意,因为我实际上正在修改UINavigationBar的全局状态。下一步是将这个方法调用viewWillAppear并且大部分时间都可以,但是当我从这个ComboFeedViewController移动到应该有这个边界的那个......好吧,它会立即被绘制。

我希望它在转换结束时或在最佳情况下显示,显示为转换。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

请查看Apple的Customizing UINavigationBar示例代码。这个例子在定制导航栏方面有很多基础。

如果您想直观地修改导航栏,但只能在导航堆栈的其中一个屏幕中看到该修改,那么最好的办法就是将这两种方法联系起来:

  • viewWillAppear:用于修改栏中的内容
  • viewWillDisappear:隐藏修改

didAppear或didDisappear方法也适用于您。但我发现挂钩willAppear / willDisappear变种并尊重动画参数为我创造了奇迹。

这里的示例代码取自我的一个项目,该项目隐藏了导航栏下方的细线(边框)(如果您想在其中一个屏幕中将UIToolbar粘贴在UINavigationBar下方,则有用)双倍大小的酒吧):

class ViewController: UIViewController {
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // We need to hide the hairline, so the bar appears
        // continous with the toolbar below it.
        navigationController?.navigationBar.setHairlineEnabled(false, animated: animated)
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        navigationController?.navigationBar.setHairlineEnabled(true, animated: animated)
    }
}

extension UINavigationBar {
    /// Hides the hairline below the navigation bar by walking
    /// the subview hierarchy and finding a 0.5 or 1 pt tall view.
    func setHairlineEnabled(enabled: Bool, animated: Bool) {
        guard subviews.count > 0 else { return }

        let firstSubview = subviews[0]

        for subview in firstSubview.subviews {
            let height = subview.bounds.height

            if height == CGFloat(0.5) || height == CGFloat(1.0) {
                let work = {
                    subview.alpha = enabled ? CGFloat(1) : CGFloat(0)
                }

                if animated {
                    UIView.animateWithDuration(NSTimeInterval(UINavigationControllerHideShowBarDuration), animations: {
                        work()
                    })
                } else {
                    work()
                }

                break
            }
        }
    }
}

答案 1 :(得分:0)

虽然批准的答案似乎解决了我的问题,但我已经面临一些问题从我的应用的特定视图转换。主要是因为当向后滑动手势开始时会立即触发viewVillAppear

缺陷是如此之小,甚至不值得花费大量时间在它上面,但它仍然在我的脑海中,所以......我找到了一个名为{{的库3}} swizzles 方法,因此您可以为每个视图控制器设置不同的导航栏外观 - 这正是我所寻找的。

现在我可以简单地将showBorderhideBorder cusstom方法放在特定视图控制器的viewDidLoad中,一切正常!