Search code examples
swiftuitableviewheaderuibezierpathrounded-corners

Rounded tableview header swift


I am trying to add a rounded tableview header on top of a tableview. Its top is below an image:

enter image description here

so my idea was to draw a shaped view and add this view as a header. But from the solutions I saw, all I was able to was this kind of shape:

enter image description here

My question is: how to have this view without the extra hight? So no hight below the corners. Any other way to have achieve design is also good.

my code:

import UIKit
import PlaygroundSupport


let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 500))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView


let headerView = UIView()

let frame2 = CGRect(x: 0, y: 190, width: 300, height: 40)
headerView.clipsToBounds = true

headerView.backgroundColor = .red
headerView.frame = frame2

headerView.roundCorners([.topLeft, .topRight], radius: 40)
containerView.addSubview(headerView)

extension UIView {

func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
}
}

Solution

  • I found out a way:

    import UIKit
    import PlaygroundSupport
    
    
    let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 500))
    containerView.backgroundColor = .white
    PlaygroundPage.current.liveView = containerView
    
    
    let headerView = UIView()
    let frame2 = CGRect(x: 0, y: 190, width: 300, height: 22)
    headerView.clipsToBounds = true
    
    headerView.backgroundColor = .red
    headerView.frame = frame2
    draw(shapeView: headerView)
    containerView.addSubview(headerView)
    
    func draw(shapeView:UIView) {
        let path = headerView.headerBezierPath(hight: headerView.frame.height).cgPath
        let shape = CAShapeLayer()
        shape.path = path
        shapeView.layer.mask = shape
    }
    
    extension UIView {
        func headerBezierPath(hight:CGFloat) -> UIBezierPath {
            let cardRadius = CGFloat(hight)
            let viewSize = self.bounds.size
            let path = UIBezierPath()
            path.move(to: CGPoint(x: cardRadius, y: 0))
        
            // top line
            path.addLine(to: CGPoint(x: viewSize.width - cardRadius, y: 0))
    
            // top-right corner arc
            path.addArc(withCenter: 
            CGPoint(x: viewSize.width - cardRadius, y: cardRadius),
            radius: cardRadius,
            startAngle: CGFloat(Double.pi * 3 / 2),
            endAngle: CGFloat(0),
            clockwise: true)
    
            // bottom line
            path.addLine(to: CGPoint(x: 0, y: cardRadius))
        
            // top-left corner arc
           path.addArc(
              withCenter: CGPoint(x: cardRadius, y: cardRadius),
          radius: cardRadius,
          startAngle: CGFloat(Double.pi),
          endAngle: CGFloat(Double.pi / 2 * 3),
          clockwise: true
            )
        
            // close path join to origin
            path.close()
            // Set the background color of the view
            UIColor.gray.set()
            path.fill()
        
            return path
        }
    }
    

    enter image description here