Skip to content

Instantly share code, notes, and snippets.

@gokselkoksal
Last active June 22, 2020 17:07
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gokselkoksal/19512553214e208571b345bc02bdf595 to your computer and use it in GitHub Desktop.
Save gokselkoksal/19512553214e208571b345bc02bdf595 to your computer and use it in GitHub Desktop.
class Button: UIButton {
var outset: CGSize = CGSize.zero
var shouldFitContentVertically: Bool = false {
didSet {
if shouldFitContentVertically {
titleLabel?.lineBreakMode = .byWordWrapping
titleLabel?.numberOfLines = 0
}
}
}
private var cachedFrame: CGRect = .zero
private let buttonEdgeOffset: CGFloat = 6 // Magic UIKit offset for buttons.
override func didMoveToSuperview() {
super.didMoveToSuperview()
cachedFrame = frame
}
override func layoutSubviews() {
super.layoutSubviews()
if frame.width != cachedFrame.width {
invalidateIntrinsicContentSize()
}
cachedFrame = frame
}
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
guard shouldFitContentVertically, let titleLabel = titleLabel else { return size }
let fittingSize = titleLabel.systemLayoutSizeFitting(CGSize(width: bounds.width, height: .greatestFiniteMagnitude))
let fitHeight = fittingSize.height
+ (contentEdgeInsets.top + contentEdgeInsets.bottom)
+ (titleEdgeInsets.top + titleEdgeInsets.bottom)
+ (buttonEdgeOffset * 2)
size.height = max(size.height, fitHeight)
return size
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard !isHidden else { return nil }
let touchableRect = self.bounds.insetBy(dx: -outset.width, dy: -outset.height)
return touchableRect.contains(point) ? self: nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment