将子图层添加到导航栏与过渡冲突



我需要在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移动到应该有这个边框的那个时......好吧,它立即被绘制。

我希望它在过渡结束时显示,或者在最好的情况下,与过渡一起出现。我怎样才能做到这一点?

请查看 Apple 的自定义 UINavigationBar 示例代码。该示例在自定义导航栏方面涵盖了很多方面。

如果要直观地修改导航栏,但仅在导航堆栈中的一个屏幕中显示该修改,则最好的办法是挂钩到以下两种方法:

  • viewWillAppear:修改栏中的某些内容
  • viewWillDisappear:隐藏该修改

didAppear或didDisappear方法也可以为您工作。但我发现钩入 willAppear/willDisappear 变体并尊重动画参数对我来说创造了奇迹。

下面是从我的一个项目中取出的示例代码,它隐藏了导航栏下方的发际线(边框((如果您想在其中一个屏幕中的 UINavigationBar 下方粘贴 UIToolbar 以具有双倍大小的条形图,则很有用(:

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
            }
        }
    }
}

虽然批准的答案似乎可以解决我的问题,但我在从应用程序的特定视图过渡时遇到了一些问题。 主要是因为当向后滑动手势开始时会立即触发viewVillAppear

缺陷太小了,甚至不值得花很多时间在上面,但它仍然在我脑海中的某个地方,所以......我找到了一个名为 KMNavigationBarTransition 的库,它可以切换方法,因此您可以为每个视图控制器设置不同的导航栏外观 - 这正是我正在寻找的。

现在,我可以简单地将我的showBorderhideBorder cusstom方法放在特定的视图控制器viewDidLoad,一切都完美无缺! 👌

最新更新