Skip to content

Instantly share code, notes, and snippets.

@samuelbeek
Created May 1, 2017 09:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samuelbeek/23bbf0f487c76073a579bcc257ef947c to your computer and use it in GitHub Desktop.
Save samuelbeek/23bbf0f487c76073a579bcc257ef947c to your computer and use it in GitHub Desktop.
Button that contains image and title. Their relative position can be modified.
//
// ImageTitleButton.swift
// Coyote
//
// Created by Samuel Beek on 01/05/2017.
// Copyright © 2017 Samuel Beek. All rights reserved.
//
import UIKit
/// Button that contains image and title. Their relative position can be modified.
class ImageTitleButton: UIButton {
override var intrinsicContentSize: CGSize {
var result = super.intrinsicContentSize
switch titlePosition {
case .top:
fallthrough
case .bottom:
result.height += spacing
case .left:
fallthrough
case .right:
result.width += spacing
default:
break
}
return result
}
/// Relative position of the title
public var titlePosition: UIViewContentMode = .right {
didSet {
updateImageInset()
}
}
/// Spacing between title and image
var spacing: CGFloat = 0 {
didSet {
updateImageInset()
}
}
/// Updates the insets based on the relative image/title position and the spacing
private func updateImageInset() {
if let title = currentTitle {
positionLabelRespectToImage(title: title, position: titlePosition, spacing: spacing)
}
}
override func setImage(_ image: UIImage?, for state: UIControlState) {
super.setImage(image, for: state)
updateImageInset()
}
override func setTitle(_ title: String?, for state: UIControlState) {
super.setTitle(title, for: state)
updateImageInset()
}
/// Sets the righ position of label and image
///
/// - Parameters:
/// - title: title to be displayed
/// - position: relative position of title
/// - spacing: spacing between title and image
private func positionLabelRespectToImage(title: String, position: UIViewContentMode, spacing: CGFloat) {
let imageSize = imageRect(forContentRect: frame)
let titleFont = titleLabel?.font
let titleSize = title.size(attributes: [NSFontAttributeName: titleFont ?? UIFont.systemFont(ofSize: 10)])
var titleEdgeInsets: UIEdgeInsets
var imageEdgeInsets: UIEdgeInsets
switch position {
case .top:
titleEdgeInsets = UIEdgeInsets(top: -(imageSize.height + titleSize.height + spacing), left: -(imageSize.width), bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -titleSize.width)
case .bottom:
titleEdgeInsets = UIEdgeInsets(top: (imageSize.height + titleSize.height + spacing), left: -(imageSize.width), bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -titleSize.width)
case .left:
titleEdgeInsets = UIEdgeInsets(top: 0, left: -(imageSize.width * 2), bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -(titleSize.width * 2 + spacing))
case .right:
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -spacing)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
default:
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
self.titleEdgeInsets = titleEdgeInsets
self.imageEdgeInsets = imageEdgeInsets
invalidateIntrinsicContentSize()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment