Don_Mag icon

Notched Tab View

Don_Mag | PRO | 05/15/25 02:22:16 PM UTC | 0 ⭐ | 10974 👁️ | Never ⏰ | []
Swift |

4.31 KB

|

None

|

0 👍

/

0 👎

// Shape with indented Notched Tab View
// based on: DuncanMC's https://github.com/DuncanMC/ShapeWithTab
 
class ShapeWithNotchedTabView: UIView {
    
    var cornerRadius: CGFloat = 20
    var tabRadius: CGFloat = 60
    
    var roundedCorners: Bool = true { didSet { setNeedsLayout() } }
    
    var shapeLayer = CAShapeLayer()
    
    func buildShapeLayerPath() -> CGPath {
        let boxWidth = bounds.size.width
        let boxHeight = bounds.size.height
        
        // These are the corners of the view's primary rectangle
        // top-right
        let point1 = CGPoint(x: boxWidth, y: 0)
        // bottom-right
        let point2 = CGPoint(x: boxWidth, y: boxHeight)
        // bottom-left
        let point3 = CGPoint(x: 0, y: boxHeight)
        // top-left
        let point4 = CGPoint(x: 0, y: 0)
        
        // These are the corners of the "tab notch" that is inset from the top of the view
        let tabPoint1 = CGPoint(x: boxWidth / 2 - tabRadius, y: 0)
        let tabPoint2 = CGPoint(x: boxWidth / 2, y: tabRadius * 2)
        let tabPoint3 = CGPoint(x: boxWidth / 2 + tabRadius , y: 0)
        
        let path = CGMutablePath()
        
        // if we want rounded corners
        if roundedCorners {
            path.move(to: CGPoint(x: boxWidth, y: boxHeight - cornerRadius))
            
            path.addArc(tangent1End: point2,
                        tangent2End: point3,
                        radius: cornerRadius)
            path.addArc(tangent1End: point3,
                        tangent2End: point4,
                        radius: cornerRadius)
            path.addArc(tangent1End: point4,
                        tangent2End: tabPoint1,
                        radius: cornerRadius)
        } else {
            path.move(to: point1)
            path.addLine(to: point2)
            path.addLine(to: point3)
            path.addLine(to: point4)
            
        }
        
        // Draw the corner that curves around to our
        //  indented "circle tab notch" at the top
        // of the shape
        path.addArc(tangent1End: tabPoint1,
                    tangent2End: tabPoint2,
                    radius: cornerRadius)
        
        // Draw the "circle tab notch"
        path.addArc(tangent1End: tabPoint2,
                    tangent2End: tabPoint3,
                    radius: tabRadius)
        
        // Draw the corner from the circle tab notch back to the top of the rect
        path.addArc(tangent1End: tabPoint3,
                    tangent2End: point1,
                    radius: cornerRadius)
        
        if roundedCorners {
            // Draw the rest of the rounded rectangle
            path.addArc(tangent1End: point1,
                        tangent2End: point2,
                        radius: cornerRadius)
        } else {
            // Draw the rest of the rectangle
            path.addLine(to: point1)
        }
        
        path.closeSubpath()
        
        return path
    }
    
    func doInitSetup() {
        self.layer.addSublayer(shapeLayer)
        
        // Configure a shape layer to draw an outline
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.lineWidth = 2
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.doInitSetup()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.doInitSetup()
    }
    
    public func updateShapeLayerPath() {
        let path = buildShapeLayerPath()
        shapeLayer.path =  path
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.frame = bounds
        updateShapeLayerPath()
    }
}
 
// example controller
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
 
        let v = ShapeWithNotchedTabView()
        v.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(v)
        
        NSLayoutConstraint.activate([
            v.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20.0),
            v.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20.0),
            v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            v.heightAnchor.constraint(equalToConstant: 120.0),
        ])
 
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textAlignment = .center
        label.numberOfLines = 0
        label.text = "Tap anywhere to toggle rounded corners"
        view.addSubview(label)
        
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40.0),
            label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40.0),
            label.topAnchor.constraint(equalTo: v.bottomAnchor, constant: 20.0),
        ])
    }
 
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let v = view.subviews.first as? ShapeWithNotchedTabView {
            v.roundedCorners.toggle()
        }
    }
}
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎