Reputation: 5156
In Apple's examples for customizing UINavigationBar
, they demonstrate the possibility of extending the navigation bar for additional functionality by covering the bottom of the bar and recreating its drop shadow.
https://developer.apple.com/library/ios/samplecode/NavBar/Introduction/Intro.html
I'm looking to do this, but with a curved extension. In other words, a semi-circle to make the entire UINavigationBar
seem like it were a section of a big circle. See attached:
The only way I've thought about possibly doing this so far is to make a very large but contained UIView
with a large corner radius to emulate this curve. I did a test, but found that when the size of a UIView
exceeds a certain size threshold/ratio, the edges start to distort and it looks as awful as it is inefficient and strange to have a massive but clipped UIView
.
Since device sizes vary and screen-orientation changes needs to be animated without the curve distorting, is there any way to possibly produce this sort of curved UINavigationBar
?
Upvotes: 1
Views: 1240
Reputation: 4738
The only method I came out for now is subclassing UINavigationBar
and drawing the shape you want using 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)
}
}
Result:
The problem is that the added pathLayer
will cover the layers of navigationbar's title and buttons. So if you set the fillColor of pathLayer
to color other than clear color, these buttons and titles will be invisible.
To fix the issue, you can add the title and buttons programmatically after the pathLayer
is added as I did, or use insertSublayer
to insert the pathLayer
behind the buttons and title as mentioned in this post CALayer - Place sublayer below storyboard UIButtons?
Upvotes: 1