7

I'm trying to figure out how to curve just the top of the UIViewController using Swift.

enter image description here

I want it curved like it shows in this photo.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
Doughnut Man
  • 164
  • 1
  • 1
  • 8

2 Answers2

11

You could draw the background with some bezier curves which shouldn't be too hard to do. You especially want to do this if you want to recreate something like into the bottom of that example as well.

Here's a custom view you can use. it just overrides the drawing and makes its background with a bezier path that has a rounded top

You can just adjust the height and curve with the static values I inserted.

class CurvedView: UIView {
    override func drawRect(rect: CGRect) {

        let y:CGFloat = 20
        let curveTo:CGFloat = 0

        let myBezier = UIBezierPath()
        myBezier.moveToPoint(CGPoint(x: 0, y: y))
        myBezier.addQuadCurveToPoint(CGPoint(x: rect.width, y: y), controlPoint: CGPoint(x: rect.width / 2, y: curveTo))
        myBezier.addLineToPoint(CGPoint(x: rect.width, y: rect.height))
        myBezier.addLineToPoint(CGPoint(x: 0, y: rect.height))
        myBezier.closePath()
        let context = UIGraphicsGetCurrentContext()
        CGContextSetLineWidth(context, 4.0)
        UIColor.whiteColor().setFill()
        myBezier.fill()
    }
}

Another way would be to just make a white view that is much bigger than the screen. I'm guessing 3 times the screen width. Then just set the corner radius to half of its width making it round.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
Moriya
  • 7,750
  • 3
  • 35
  • 53
  • I made a new file and named it "CurvedView" and then in UIView Custom Class i set it to that file. then i stuck your code in but now my app won't open and crashes. What did i do wrong? – Doughnut Man May 11 '16 at 13:00
  • What errors do you get? – Moriya May 11 '16 at 13:19
6

To have rounded cornered edges of View:

In case of UIViewController's default view:

override func viewWillAppear(animated: Bool) {

    self.navigationController?.navigationBarHidden =  true

    //UIView Corner Radius
    self.view.layer.cornerRadius = 20.0;
    self.view.layer.masksToBounds = true

    //UIView Set up border
    self.view.layer.borderColor = UIColor.yellowColor().CGColor;
    self.view.layer.borderWidth = 3.0;        
}

In case of the top status bar:

Make a custom View as the top status bar.

func addStatusBar()
{
    let statusBarView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.mainScreen().bounds.size.width, height: 20.0))

    statusBarView.backgroundColor = UIColor.greenColor()

    //UIView Corner Radius
    statusBarView.layer.cornerRadius = 5.0;
    statusBarView.layer.masksToBounds = true

    //UIView Set up border
    statusBarView.layer.borderColor = UIColor.yellowColor().CGColor;
    statusBarView.layer.borderWidth = 3.0;

    self.navigationController?.navigationBarHidden =  true
    self.view.addSubview(statusBarView)
}

Adding the custom status bar to view:

override func viewWillAppear(animated: Bool) {
    self.addStatusBar()
}

To make a view having rounded top:

extension UIView {

    func addTopRoundedCornerToView(targetView:UIView?, desiredCurve:CGFloat?)
    {
        let offset:CGFloat =  targetView!.frame.width/desiredCurve!
        let bounds: CGRect = targetView!.bounds

        let rectBounds: CGRect = CGRectMake(bounds.origin.x, bounds.origin.y+bounds.size.height / 2, bounds.size.width, bounds.size.height / 2)

        let rectPath: UIBezierPath = UIBezierPath(rect: rectBounds)
        let ovalBounds: CGRect = CGRectMake(bounds.origin.x - offset / 2, bounds.origin.y, bounds.size.width + offset, bounds.size.height)
        let ovalPath: UIBezierPath = UIBezierPath(ovalInRect: ovalBounds)
        rectPath.appendPath(ovalPath)

        // Create the shape layer and set its path
        let maskLayer: CAShapeLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = rectPath.CGPath

        // Set the newly created shape layer as the mask for the view's layer
        targetView!.layer.mask = maskLayer
    }
}

Usage:

override func viewWillAppear(animated: Bool) {
    self.navigationController?.navigationBarHidden =  true
    self.view.addTopRoundedCornerToView(self.view, desiredCurve: 0.6)
}
Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
Alvin George
  • 14,148
  • 92
  • 64
  • How does this code in any way "curve just the top". What you do here is just adding a small corner radius, which is not even part of the example image in the question. – Moriya May 11 '16 at 06:58
  • I have updated my answer adding a precise Rounded Top to a view. Thank you for notifying the same. – Alvin George May 11 '16 at 07:51
  • @AlvinGeorge I want to add a border on that top curve. I tried adding CAShapeLayer() as a border, but it is not working as expected. Can you please suggest. – Mitesh Dobareeya May 13 '22 at 08:54