Advertisement
Don_Mag

Notched Tab View

May 15th, 2025
932
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 4.31 KB | None | 0 0
  1. // Shape with indented Notched Tab View
  2. // based on: DuncanMC's https://github.com/DuncanMC/ShapeWithTab
  3.  
  4. class ShapeWithNotchedTabView: UIView {
  5.    
  6.     var cornerRadius: CGFloat = 20
  7.     var tabRadius: CGFloat = 60
  8.    
  9.     var roundedCorners: Bool = true { didSet { setNeedsLayout() } }
  10.    
  11.     var shapeLayer = CAShapeLayer()
  12.    
  13.     func buildShapeLayerPath() -> CGPath {
  14.         let boxWidth = bounds.size.width
  15.         let boxHeight = bounds.size.height
  16.        
  17.         // These are the corners of the view's primary rectangle
  18.         // top-right
  19.         let point1 = CGPoint(x: boxWidth, y: 0)
  20.         // bottom-right
  21.         let point2 = CGPoint(x: boxWidth, y: boxHeight)
  22.         // bottom-left
  23.         let point3 = CGPoint(x: 0, y: boxHeight)
  24.         // top-left
  25.         let point4 = CGPoint(x: 0, y: 0)
  26.        
  27.         // These are the corners of the "tab notch" that is inset from the top of the view
  28.         let tabPoint1 = CGPoint(x: boxWidth / 2 - tabRadius, y: 0)
  29.         let tabPoint2 = CGPoint(x: boxWidth / 2, y: tabRadius * 2)
  30.         let tabPoint3 = CGPoint(x: boxWidth / 2 + tabRadius , y: 0)
  31.        
  32.         let path = CGMutablePath()
  33.        
  34.         // if we want rounded corners
  35.         if roundedCorners {
  36.             path.move(to: CGPoint(x: boxWidth, y: boxHeight - cornerRadius))
  37.            
  38.             path.addArc(tangent1End: point2,
  39.                         tangent2End: point3,
  40.                         radius: cornerRadius)
  41.             path.addArc(tangent1End: point3,
  42.                         tangent2End: point4,
  43.                         radius: cornerRadius)
  44.             path.addArc(tangent1End: point4,
  45.                         tangent2End: tabPoint1,
  46.                         radius: cornerRadius)
  47.         } else {
  48.             path.move(to: point1)
  49.             path.addLine(to: point2)
  50.             path.addLine(to: point3)
  51.             path.addLine(to: point4)
  52.            
  53.         }
  54.        
  55.         // Draw the corner that curves around to our
  56.         //  indented "circle tab notch" at the top
  57.         // of the shape
  58.         path.addArc(tangent1End: tabPoint1,
  59.                     tangent2End: tabPoint2,
  60.                     radius: cornerRadius)
  61.        
  62.         // Draw the "circle tab notch"
  63.         path.addArc(tangent1End: tabPoint2,
  64.                     tangent2End: tabPoint3,
  65.                     radius: tabRadius)
  66.        
  67.         // Draw the corner from the circle tab notch back to the top of the rect
  68.         path.addArc(tangent1End: tabPoint3,
  69.                     tangent2End: point1,
  70.                     radius: cornerRadius)
  71.        
  72.         if roundedCorners {
  73.             // Draw the rest of the rounded rectangle
  74.             path.addArc(tangent1End: point1,
  75.                         tangent2End: point2,
  76.                         radius: cornerRadius)
  77.         } else {
  78.             // Draw the rest of the rectangle
  79.             path.addLine(to: point1)
  80.         }
  81.        
  82.         path.closeSubpath()
  83.        
  84.         return path
  85.     }
  86.    
  87.     func doInitSetup() {
  88.         self.layer.addSublayer(shapeLayer)
  89.        
  90.         // Configure a shape layer to draw an outline
  91.         shapeLayer.fillColor = UIColor.white.cgColor
  92.         shapeLayer.strokeColor = UIColor.blue.cgColor
  93.         shapeLayer.lineWidth = 2
  94.     }
  95.    
  96.     override init(frame: CGRect) {
  97.         super.init(frame: frame)
  98.         self.doInitSetup()
  99.     }
  100.    
  101.     required init?(coder: NSCoder) {
  102.         super.init(coder: coder)
  103.         self.doInitSetup()
  104.     }
  105.    
  106.     public func updateShapeLayerPath() {
  107.         let path = buildShapeLayerPath()
  108.         shapeLayer.path =  path
  109.     }
  110.    
  111.     override func layoutSubviews() {
  112.         super.layoutSubviews()
  113.         shapeLayer.frame = bounds
  114.         updateShapeLayerPath()
  115.     }
  116. }
  117.  
  118. // example controller
  119.  
  120. class ViewController: UIViewController {
  121.  
  122.     override func viewDidLoad() {
  123.         super.viewDidLoad()
  124.         view.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
  125.  
  126.         let v = ShapeWithNotchedTabView()
  127.         v.translatesAutoresizingMaskIntoConstraints = false
  128.         view.addSubview(v)
  129.        
  130.         NSLayoutConstraint.activate([
  131.             v.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
  132.             v.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20.0),
  133.             v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
  134.             v.heightAnchor.constraint(equalToConstant: 120.0),
  135.         ])
  136.  
  137.         let label = UILabel()
  138.         label.translatesAutoresizingMaskIntoConstraints = false
  139.         label.textAlignment = .center
  140.         label.numberOfLines = 0
  141.         label.text = "Tap anywhere to toggle rounded corners"
  142.         view.addSubview(label)
  143.        
  144.         NSLayoutConstraint.activate([
  145.             label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40.0),
  146.             label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40.0),
  147.             label.topAnchor.constraint(equalTo: v.bottomAnchor, constant: 20.0),
  148.         ])
  149.     }
  150.  
  151.     override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  152.         if let v = view.subviews.first as? ShapeWithNotchedTabView {
  153.             v.roundedCorners.toggle()
  154.         }
  155.     }
  156. }
  157.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement