Skip to content

Instantly share code, notes, and snippets.

@acalism
Last active October 26, 2024 05:12
Show Gist options
  • Save acalism/fa429d4787e0015113bda5eaad550b9a to your computer and use it in GitHub Desktop.
Save acalism/fa429d4787e0015113bda5eaad550b9a to your computer and use it in GitHub Desktop.
扩大了响应范围的 button,提供了两种办法
private var ExtendEdgeInsetsKey: Void?
extension UIButton {
/// 设置此属性即可扩大响应范围, 分别对应上左下右
/// 优势:与Auto-Layout无缝配合
/// 劣势:View Debugger 查看不到增加的响应区域有多大,
var extendEdgeInsets: UIEdgeInsets {
get {
return objc_getAssociatedObject(self, &ExtendEdgeInsetsKey) as? UIEdgeInsets ?? UIEdgeInsets.zero
}
set {
objc_setAssociatedObject(self, &ExtendEdgeInsetsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if UIEdgeInsetsEqualToEdgeInsets(extendEdgeInsets, .zero) || !self.isEnabled || self.isHidden || self.alpha < 0.01 {
return super.point(inside: point, with: event)
}
let newRect = extendRect(bounds, extendEdgeInsets)
return newRect.contains(point)
}
private func extendRect(_ rect: CGRect, _ edgeInsets: UIEdgeInsets) -> CGRect {
let x = rect.minX - edgeInsets.left
let y = rect.minY - edgeInsets.top
let w = rect.width + edgeInsets.left + edgeInsets.right
let h = rect.height + edgeInsets.top + edgeInsets.bottom
return CGRect(x: x, y: y, width: w, height: h)
}
}
// MARK: - 用contentInset的方式增加响应区域(同时增加其frame)
/// 使用示例:
/// button.contentInset = UIEdgeInsets(top: 10, left: 20, bottom: 15, right: 18)
/// button.sizeToFit()
/// button.contentCenter = CGPoint(x: button.superview!.frame.maxX - 8 - button.contentFrame.width / 2, y: 100)
/// 注意:使用 frame 和 center 的地方都相应地换成 contentFrame 和 contentCenter,而bounds与frame相对应
///
/// 优势:View Debugger 或 FLEX 看到的 button 大小即为响应区域,所见即所得
/// 劣势:和 Auto-Layout 配合繁琐
extension UIButton {
var contentFrame: CGRect {
get { return UIEdgeInsetsInsetRect(frame, contentEdgeInsets) }
set { frame = UIEdgeInsetsInsetRect(newValue, -contentEdgeInsets) }
}
var contentCenter: CGPoint {
get {
return CGPoint(x: (frame.minX + contentEdgeInsets.left + frame.maxX - contentEdgeInsets.right) / 2, y: (frame.minY + contentEdgeInsets.top + frame.maxY - contentEdgeInsets.bottom) / 2)
}
set {
frame.origin = CGPoint(x: newValue.x - contentFrame.width / 2 - contentEdgeInsets.left, y: newValue.y - contentFrame.height / 2 - contentEdgeInsets.top)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment