|
// |
|
// 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() |
|
} |
|
} |