Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import UIKit
enum LayoutableButtonVerticalAlignment: String {
case center
case top
case bottom
case unset
}
enum LayoutableButtonHorizontalAlignment: String {
case center
case left
case right
case unset
}
@IBDesignable
class LayoutableButton: UIButton {
@IBInspectable
var imageToTitleSpacing: CGFloat = 8.0 {
didSet {
setNeedsLayout()
}
}
var imageVerticalAlignment: LayoutableButtonVerticalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
var imageHorizontalAlignment: LayoutableButtonHorizontalAlignment = .unset {
didSet {
setNeedsLayout()
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageVerticalAlignment' instead.")
@IBInspectable
var imageVerticalAlignmentName: String! {
willSet {
if let newImageVerticalAlignmentName = LayoutableButtonVerticalAlignment(rawValue: newValue.lowercased()) {
imageVerticalAlignment = newImageVerticalAlignmentName
}
}
}
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'imageHorizontalAlignmentName' instead.")
@IBInspectable
var imageHorizontalAlignmentName: String! {
willSet {
if let newImageHorizontalAlignmentName = LayoutableButtonHorizontalAlignment(rawValue: newValue.lowercased()) {
imageHorizontalAlignment = newImageHorizontalAlignmentName
}
}
}
var extraContentEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero
override var contentEdgeInsets: UIEdgeInsets {
get {
return super.contentEdgeInsets
}
set {
super.contentEdgeInsets = newValue
self.extraContentEdgeInsets = newValue
}
}
var extraImageEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero
override var imageEdgeInsets: UIEdgeInsets {
get {
return super.imageEdgeInsets
}
set {
super.imageEdgeInsets = newValue
self.extraImageEdgeInsets = newValue
}
}
var extraTitleEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero
override var titleEdgeInsets: UIEdgeInsets {
get {
return super.titleEdgeInsets
}
set {
super.titleEdgeInsets = newValue
self.extraTitleEdgeInsets = newValue
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageEdgeInsets = super.imageEdgeInsets
self.titleEdgeInsets = super.titleEdgeInsets
self.contentEdgeInsets = super.contentEdgeInsets
}
override init(frame: CGRect) {
super.init(frame: frame)
}
override func layoutSubviews() {
if let imageSize = self.imageView?.image?.size,
let font = self.titleLabel?.font,
let textSize = self.titleLabel?.attributedText?.size() ?? self.titleLabel?.text?.size(attributes: [NSFontAttributeName: font]) {
var imageEdgeInsets = UIEdgeInsets.zero
var titleEdgeInsets = UIEdgeInsets.zero
var contentEdgeInsets = UIEdgeInsets.zero
let halfImageToTitleSpacing = imageToTitleSpacing / 2.0
switch imageVerticalAlignment {
case .bottom:
imageEdgeInsets.top = (textSize.height + imageToTitleSpacing) / 2.0
imageEdgeInsets.bottom = (-textSize.height - imageToTitleSpacing) / 2.0
titleEdgeInsets.top = (-imageSize.height - imageToTitleSpacing) / 2.0
titleEdgeInsets.bottom = (imageSize.height + imageToTitleSpacing) / 2.0
contentEdgeInsets.top = (min(imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
contentEdgeInsets.bottom = (min(imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .top:
imageEdgeInsets.top = (-textSize.height - imageToTitleSpacing) / 2.0
imageEdgeInsets.bottom = (textSize.height + imageToTitleSpacing) / 2.0
titleEdgeInsets.top = (imageSize.height + imageToTitleSpacing) / 2.0
titleEdgeInsets.bottom = (-imageSize.height - imageToTitleSpacing) / 2.0
contentEdgeInsets.top = (min(imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
contentEdgeInsets.bottom = (min(imageSize.height, textSize.height) + imageToTitleSpacing) / 2.0
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
case .center:
//only works with contentVerticalAlignment = .center
contentVerticalAlignment = .center
break
case .unset:
break
}
switch imageHorizontalAlignment {
case .left:
imageEdgeInsets.left = -halfImageToTitleSpacing
imageEdgeInsets.right = halfImageToTitleSpacing
titleEdgeInsets.left = halfImageToTitleSpacing
titleEdgeInsets.right = -halfImageToTitleSpacing
contentEdgeInsets.left = halfImageToTitleSpacing
contentEdgeInsets.right = halfImageToTitleSpacing
case .right:
imageEdgeInsets.left = textSize.width + halfImageToTitleSpacing
imageEdgeInsets.right = -textSize.width - halfImageToTitleSpacing
titleEdgeInsets.left = -imageSize.width - halfImageToTitleSpacing
titleEdgeInsets.right = imageSize.width + halfImageToTitleSpacing
contentEdgeInsets.left = halfImageToTitleSpacing
contentEdgeInsets.right = halfImageToTitleSpacing
case .center:
imageEdgeInsets.left = textSize.width / 2.0
imageEdgeInsets.right = -textSize.width / 2.0
titleEdgeInsets.left = -imageSize.width / 2.0
titleEdgeInsets.right = imageSize.width / 2.0
contentEdgeInsets.left = -((imageSize.width + textSize.width) - max(imageSize.width, textSize.width)) / 2.0
contentEdgeInsets.right = -((imageSize.width + textSize.width) - max(imageSize.width, textSize.width)) / 2.0
case .unset:
break
}
contentEdgeInsets.top += extraContentEdgeInsets.top
contentEdgeInsets.bottom += extraContentEdgeInsets.bottom
contentEdgeInsets.left += extraContentEdgeInsets.left
contentEdgeInsets.right += extraContentEdgeInsets.right
imageEdgeInsets.top += extraImageEdgeInsets.top
imageEdgeInsets.bottom += extraImageEdgeInsets.bottom
imageEdgeInsets.left += extraImageEdgeInsets.left
imageEdgeInsets.right += extraImageEdgeInsets.right
titleEdgeInsets.top += extraTitleEdgeInsets.top
titleEdgeInsets.bottom += extraTitleEdgeInsets.bottom
titleEdgeInsets.left += extraTitleEdgeInsets.left
titleEdgeInsets.right += extraTitleEdgeInsets.right
super.imageEdgeInsets = imageEdgeInsets
super.titleEdgeInsets = titleEdgeInsets
super.contentEdgeInsets = contentEdgeInsets
} else {
super.imageEdgeInsets = extraImageEdgeInsets
super.titleEdgeInsets = extraTitleEdgeInsets
super.contentEdgeInsets = extraContentEdgeInsets
}
super.layoutSubviews()
}
}
@nebiros

This comment has been minimized.

Copy link
Owner Author

commented Feb 28, 2017

@hemangshah

This comment has been minimized.

Copy link

commented Apr 1, 2018

Hi @Nebrios, how to make it work for the Arabic language? Because when I use the same code for it works totally different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.