Этот вопрос проверяет понимание обработки событий касания в UIKit и умение расширять интерактивную область элемента без изменения его видимой части.
В UIKit система обработки событий касания (touch handling) для определения того, какая view должна получить событие, использует методы hitTest(_:with:) и point(inside:with:). Метод point(inside:with:) возвращает true, если переданная точка находится в пределах bounds view. Именно этот метод можно переопределить, чтобы "обмануть" систему и заставить кнопку реагировать на касания за пределами её видимого фрейма.
Самый чистый способ — создать подкласс UIButton и переопределить point(inside:with:). Внутри метода мы расширяем прямоугольник, в котором считается валидным касание, используя insetBy(dx:dy:) с отрицательными значениями. Эти значения определяют, насколько нужно увеличить область с каждой стороны.
class ExtendedTouchAreaButton: UIButton {
var touchAreaPadding: UIEdgeInsets = .zero
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let extendedRect = bounds.inset(by: UIEdgeInsets(
top: -touchAreaPadding.top,
left: -touchAreaPadding.left,
bottom: -touchAreaPadding.bottom,
right: -touchAreaPadding.right
))
return extendedRect.contains(point)
}
}Этот подход полезен в нескольких сценариях:
Важно помнить, что расширенная область не отрисовывается и не влияет на layout других элементов. Она влияет только на hit-testing.
Если нежелательно создавать подкласс кнопки, можно управлять областью на уровне родительской view, переопределяя её hitTest(_:with:). Однако это менее точно и может затронуть другие дочерние view.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
if view == targetButton {
let extendedPoint = targetButton.convert(point, from: self)
if targetButton.point(inside: extendedPoint, with: event) {
return targetButton
}
}
return view
}Вывод: Переопределение point(inside:with:) в подклассе UIButton — это предпочтительный и чистый способ увеличить область нажатия. Его стоит применять для улучшения юзабилити интерфейса на мобильных устройствах, особенно когда целевые элементы имеют маленький визуальный размер.