`UINavigationBar` 弯曲扩展?

Posted

技术标签:

【中文标题】`UINavigationBar` 弯曲扩展?【英文标题】:`UINavigationBar` curved extension? 【发布时间】:2016-06-13 05:37:56 【问题描述】:

在 Apple 的自定义 UINavigationBar 示例中,它们展示了通过覆盖导航栏底部并重新创建其投影来扩展导航栏以获得更多功能的可能性。 https://developer.apple.com/library/ios/samplecode/NavBar/Introduction/Intro.html

我希望这样做,但要使用弯曲的扩展。换句话说,一个半圆使整个UINavigationBar 看起来像是一个大圆的一部分。 见附件:

到目前为止,我考虑过的唯一方法是制作一个非常大但包含的UIView,具有较大的圆角半径来模拟这条曲线。我做了一个测试,但发现当UIView 的大小超过某个大小阈值/比率时,边缘开始扭曲,看起来很糟糕,因为它效率低下,而且很奇怪,但有一个巨大但被剪裁的UIView

由于设备尺寸各不相同,屏幕方向的变化需要在不扭曲曲线的情况下进行动画处理,有没有办法可以产生这种曲线UINavigationBar

【问题讨论】:

***.com/questions/25569210/… 这可能会有所帮助 @iAnurag 与背景图像一起使用,考虑到我提到的约束(用于动态处理旋转和各种屏幕尺寸),这将不起作用... @jtbandes 我在考虑UIBezierPath,但我不知道如何让它在这种情况下工作。 【参考方案1】:

我现在唯一的方法是继承UINavigationBar并使用CAShapeLayer绘制你想要的形状:

import UIKit

class CustomNavigationBar: UINavigationBar 

    var pathLayer: CAShapeLayer?

    init() 
        super.init(frame: CGRectZero)

        setup()
    

    override init(frame: CGRect) 
        super.init(frame: frame)

        setup()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)

        setup()
    

    override func drawRect(rect: CGRect) 

        super.drawRect(rect)
    

    func setup() 
        var bezierPath = UIBezierPath()
        bezierPath.moveToPoint(CGPointMake(0.0, 31.47))
        bezierPath.addCurveToPoint(CGPointMake(186.72, 42.5), controlPoint1: CGPointMake(0.5, 31.47), controlPoint2: CGPointMake(93.22, 42.5))
        bezierPath.addCurveToPoint(CGPointMake(375, 31.47), controlPoint1: CGPointMake(280.22, 42.5), controlPoint2: CGPointMake(375, 31.47))
        bezierPath.addLineToPoint(CGPointMake(375, -0.5))
        bezierPath.addLineToPoint(CGPointMake(0.5, -0.5))
        bezierPath.addLineToPoint(CGPointMake(0.0, 31.47))
        UIColor.blackColor().setStroke()
        bezierPath.lineWidth = 1
        bezierPath.stroke()

        pathLayer = CAShapeLayer()
        pathLayer?.fillColor = UIColor.lightGrayColor().CGColor
        pathLayer?.path = bezierPath.CGPath
        pathLayer?.lineWidth = 1.0
        pathLayer?.strokeColor = UIColor.blackColor().CGColor
        layer.addSublayer(pathLayer!)

        let title = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 30))
        title.text = "Title"
        title.textAlignment = .Center
        title.center = self.center
        addSubview(title)

    

结果:

问题是添加的pathLayer 会覆盖导航栏的标题和按钮层。所以如果你将pathLayer的fillColor设置为透明色以外的颜色,这些按钮和标题将是不可见的。

要解决此问题,您可以像我一样在添加pathLayer 之后以编程方式添加标题和按钮,或者使用insertSublayer 在按钮和标题后面插入pathLayer,如本文@987654322 中所述@

【讨论】:

嗯,这必须在UINavigationBar 的范围内吗? 不行,可以超出UINavigationBar的范围

以上是关于`UINavigationBar` 弯曲扩展?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIViewController 在 UINavigationBar 下扩展,而 UITableViewController 没有?

iOS 7 UITableView 在 UINavigationBar 下扩展

UISearchBar 在 UINavigationBar 后面扩展

iOS 7 - 使 UINavigationBar 扩展到屏幕顶部

一段时间后,ios7 UINavigationBar 在状态栏下停止扩展

iOS 11 UINavigationBar 自定义背景总是在状态栏下扩展