UIKit · · 4 min read

How to Create Top/Bottom Rounded Corners for Views and Buttons

How to Create Top/Bottom Rounded Corners for Views and Buttons

We are launching a new series of tutorials to answer some of the common questions. The questions can be simple ones from beginners and tough ones that require some works. One of the questions is:

I know how to create rounded corners of a view or button. But what if I just want to create a view with top/bottom rounded corners only? How can I do it in Swift?

Okay, let’s revisit how you create rounded corners for a view. Apple has made it very easy to create views with rounded corner. All you need to do is set the cornerRadius property of a view’s layer and set clipsToBounds to true. Here is the code snippet:

self.view.layer.cornerRadius = 20.0
self.view.clipToBounds = true

To visualize the implementation, you can create a Playgrounds project and fill in the code like this:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    
    var cardView: UIView!
    
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .black

        cardView = UIView()
        view.addSubview(cardView)
        
        cardView.translatesAutoresizingMaskIntoConstraints = false
        cardView.widthAnchor.constraint(equalToConstant: 200).isActive = true
        cardView.heightAnchor.constraint(equalToConstant: 200).isActive = true
        cardView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        cardView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        
        cardView.backgroundColor = UIColor(red: 1.0, green: 0.784, blue: 0.2, alpha: 1.0)
        
        self.view = view
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        cardView.roundCorners(cornerRadius: 20.0)
    }


}

extension UIView {
    func roundCorners(cornerRadius: Double) {
        self.layer.cornerRadius = CGFloat(cornerRadius)
        self.clipsToBounds = true
    }
    
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

If you switch to the Assistant editor mode, you should see the view rendered like this. The view in yellow has rounded corners.

That’s pretty straightforward. All the corners are rounded. But what if you don’t want to round all the corners? Say, you just want to round the top corners.

Using maskedCorners on iOS 11

In iOS 11, Apple introduced a new property named maskedCorners for the Core Animation layer (CALayer). This property is of the type CACornerMask, which has 4 possible values:

  • layerMaxXMaxYCorner – lower right corner
  • layerMaxXMinYCorner – top right corner
  • layerMinXMaxYCorner – lower left corner
  • layerMinXMinYCorner – top left corner

By default, the value of maskedCorners is set to display all the four corners. Now, let’s say you just want to round the top corners. You can set maskedCorners to the following:

self.view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

If you change the roundCorners method like below, you will only round the top corners of the view in yellow.

func roundCorners(cornerRadius: Double) {
    self.layer.cornerRadius = CGFloat(cornerRadius)
    self.clipsToBounds = true
    self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
}

Using Bezier Path on iOS 10 (or lower)

The catch of this approach is that it supports iOS 11 (or up) only. If your app needs to support lower version of iOS, you can’t use the maskedCorners property.

Here is an alternate solution. Instead of using maskedCorners, we use UIBezierPath to create a rounded rectangular path. The initialization of UIBezierPath allows us to specify the corners we want to round like this:

let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10.0, height: 10.0))

With the path, we can create a shape layer as a mask. Update the roundCorners method like this:

func roundCorners(cornerRadius: Double) {
    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
    let maskLayer = CAShapeLayer()
    maskLayer.frame = self.bounds
    maskLayer.path = path.cgPath
    self.layer.mask = maskLayer
}

We create a mask with top rounded corners and then set to the mask property of the view’s layer to mask the content. This is how we round a specific corner of a view or button on iOS 10 or lower.

But please take note that the rendering occurs after the view is appeared. Therefore, you have to call the roundCorners method in viewDidAppear() or viewDidLayoutSubviews():

override func viewDidLayoutSubviews() {
    cardView.roundCorners(cornerRadius: 20.0)
}

The result will look like this:

Animating Corners

Some readers also wondered how to animate the corners. You can use the UIView animation or the new UIViewPropertyAnimator to animate the changes.

For example, you want to animate the corners when a user taps the square view. You can first register the tap recognizer in viewDidLoad():

let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(animateCornerChange(recognizer:)))
cardView.addGestureRecognizer(tapRecognizer)

And then create the animateCornerChange method like this:

@objc func animateCornerChange(recognizer: UITapGestureRecognizer) {
    
    let targetRadius: CGFloat = (cardView.layer.cornerRadius == 0.0) ? 100.0 : 0.0
    UIViewPropertyAnimator(duration: 1.0, curve: .easeInOut) {
        self.cardView.layer.cornerRadius = targetRadius
        }.startAnimation()
}

In the code above, we use UIViewPropertyAnimator to create the animation. Alternatively, you can use the standard UIView animation to perform the change:

 UIView.animate(withDuration: 1.0, delay: 0.0, options: .curveEaseInOut, animations: {
     self.cardView.layer.cornerRadius = targetRadius
 }, completion: nil)

If you’ve updated the code in your Playground project, tapping the view will activate the animation.

That’s it for this tutorial. Stay tuned. We’ll have more articles to come. If you have any thoughts on this new series, please feel free to leave me comment below.

Editor’s note: If you want to dive deeper into iOS development, you can check out our Swift books and course.

Read next