Создать кнопку‑круг в виде бублика

Бублик рисуется двумя концентрическими окружностями с even-odd заполнением. Если отверстие не должно нажиматься, ту же кольцевую область используют в hit testing.

Короткий ответ

Что ответить на собеседовании

Бублик рисуется двумя концентрическими окружностями с even-odd заполнением. Если отверстие не должно нажиматься, ту же кольцевую область используют в hit testing.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо реализовать кнопку, оформленную как бублик, при этом должно соблюдаться условие rect.width == rect.height, а радиус окружности известен.

Ответ

Бублик рисуется двумя концентрическими окружностями с even-odd заполнением. Если отверстие не должно нажиматься, ту же кольцевую область используют в hit testing.

Для UIKit внешний радиус равен половине стороны квадратных bounds; внутренний радиус задайте отдельно:

final class DonutButton: UIButton {
    var innerRadius: CGFloat = 20 { didSet { setNeedsDisplay() } }
    private var ring: UIBezierPath {
        let outer = UIBezierPath(ovalIn: bounds)
        let hole = CGRect(x: bounds.midX - innerRadius,
                          y: bounds.midY - innerRadius,
                          width: innerRadius * 2, height: innerRadius * 2)
        outer.append(UIBezierPath(ovalIn: hole))
        outer.usesEvenOddFillRule = true
        return outer
    }
    override func draw(_ rect: CGRect) {
        tintColor.setFill()
        ring.fill()
    }
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        ring.contains(point)
    }
}

Задайте прозрачный фон, ограничения ширины/высоты 2R и 0 < innerRadius < R. Две окружности требуют внутреннего радиуса либо толщины кольца — одного внешнего радиуса недостаточно. Добавьте доступное название кнопки и визуальные состояния нажатия/disabled.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее