Вы можете сделать это с UIBezierPath
и CAShapeLayer
Создать подкласс UIButton
и переопределить layoutSubviews()
, чтогде вы обновите свой путь, соединив точки с линиями.
Вот отправная точка для вас:
class AngledButton: UIButton {
var bPath = UIBezierPath()
var theShapeLayer = CAShapeLayer()
var fillColor: UIColor = UIColor.white
var borderColor: UIColor = UIColor.gray
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
layer.addSublayer(theShapeLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
let p1 = CGPoint.zero
let p2 = CGPoint(x: bounds.width - bounds.height * 0.3, y: 0.0)
let p3 = CGPoint(x: bounds.width, y: bounds.height * 0.5)
let p4 = CGPoint(x: bounds.width - bounds.height * 0.3, y: bounds.height)
let p5 = CGPoint(x: 0.0, y: bounds.height)
bPath.move(to: p1)
bPath.addLine(to: p2)
bPath.addLine(to: p3)
bPath.addLine(to: p4)
bPath.addLine(to: p5)
bPath.close()
theShapeLayer.path = bPath.cgPath
theShapeLayer.fillColor = self.fillColor.cgColor
theShapeLayer.strokeColor = self.borderColor.cgColor
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// only allow tap *within* the bezier path
if bPath.contains(point) {
return self
}
return nil
}
}
При переопределении hitTest()
кнопка будет нажата, только есликран находится в зоне безье пути.Затем вы можете перекрывать свои кнопки, и нажатие в верхнем правом углу будет «проходить» к кнопке внизу.
Результат:
Примечания:
- Вы можете сделать это
@IBDesignable
, чтобы увидеть макет в Интерфейсном Разработчике - Вам понадобится поиграть с вкладками титров, чтобы получить заголовокметки для учета углового края
- Это только отправная точка, но она должна помочь вам