Skip to content

Instantly share code, notes, and snippets.

@DeFrenZ
Created July 9, 2015 17:06
Show Gist options
  • Save DeFrenZ/75fd810da8e5e983221d to your computer and use it in GitHub Desktop.
Save DeFrenZ/75fd810da8e5e983221d to your computer and use it in GitHub Desktop.
UIButton subclass for having the image at different positions
//
// DZPositionedImageButton.swift
// Boppl
//
// Created by Davide De Franceschi on 18/05/2015.
// Copyright (c) 2015 Boppl. All rights reserved.
//
import UIKit
@IBDesignable
public class DZPositionedImageButton: UIButton {
public enum ImagePosition: Int {
case BottomLeft = 1, BottomCenter, BottomRight, CenterLeft, CenterRight = 6, TopLeft, TopCenter, TopRight
public enum HorizontalPosition {
case Left, Center, Right
}
public var horizontalPosition: HorizontalPosition {
switch self {
case .TopLeft, .CenterLeft, .BottomLeft: return .Left
case .TopCenter, .BottomCenter: return .Center
case .TopRight, .CenterRight, .BottomRight: return .Right
}
}
public enum VerticalPosition {
case Top, Center, Bottom
}
public var verticalPosition: VerticalPosition {
switch self {
case .TopLeft, .TopCenter, .TopRight: return .Top
case .CenterLeft, .CenterRight: return .Center
case .BottomLeft, .BottomCenter, .BottomRight: return .Bottom
}
}
}
public var imagePosition: ImagePosition = .CenterLeft {
didSet { updateEdgeInsets() }
}
@IBInspectable public var imagePositionInteger: Int {
get { return imagePosition.rawValue }
set { imagePosition = ImagePosition(rawValue: newValue) ?? .CenterLeft }
}
@IBInspectable public var contentGap: CGSize = .zeroSize {
didSet { updateEdgeInsets() }
}
private var _contentEdgeInsets: UIEdgeInsets = UIEdgeInsetsZero {
didSet { updateEdgeInsets() }
}
override public var contentEdgeInsets: UIEdgeInsets {
get { return super.contentEdgeInsets }
set { _contentEdgeInsets = newValue }
}
private func updateEdgeInsets() {
let initialEdgeInsets = contentEdgeInsets
if let image = currentImage,
label = titleLabel {
let imageSize = image.size
let labelSize = label.intrinsicContentSize()
let horizontalMultiplier = { () -> CGFloat in
switch self.imagePosition.horizontalPosition {
case .Left: return -0.5
case .Center: return +0.0
case .Right: return +0.5
}
}()
let imageXOffset = +(labelSize.width * (horizontalMultiplier + 0.5) + contentGap.width * horizontalMultiplier)
let labelXOffset = -(imageSize.width * (horizontalMultiplier + 0.5) + contentGap.width * horizontalMultiplier)
let verticalMultiplier = { () -> CGFloat in
switch self.imagePosition.verticalPosition {
case .Top: return -0.5
case .Center: return +0.0
case .Bottom: return +0.5
}
}()
let imageYOffset = +(labelSize.height * verticalMultiplier + contentGap.height * verticalMultiplier)
let labelYOffset = -(imageSize.height * verticalMultiplier + contentGap.height * verticalMultiplier)
super.imageEdgeInsets = UIEdgeInsetsMake(imageYOffset, imageXOffset, -imageYOffset, -imageXOffset)
super.titleEdgeInsets = UIEdgeInsetsMake(labelYOffset, labelXOffset, -labelYOffset, -labelXOffset)
let contentWidthInset = { () -> CGFloat in
switch self.imagePosition.horizontalPosition {
case .Center: return min(imageSize.width, labelSize.width)
default: return -self.contentGap.width
}
}()
let contentHeightInset = { () -> CGFloat in
switch self.imagePosition.verticalPosition {
case .Center: return 0
default: return -(min(imageSize.height, labelSize.height) + self.contentGap.height)
}
}()
super.contentEdgeInsets = UIEdgeInsets(top: -contentHeightInset / 2, left: -contentWidthInset / 2, bottom: -contentHeightInset / 2, right: -contentWidthInset / 2) + _contentEdgeInsets
}
}
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
_contentEdgeInsets = contentEdgeInsets
}
}
public class DZLocalizedAttributedTitlePositionedImageButton: DZPositionedImageButton {
override public func awakeFromNib() {
super.awakeFromNib()
if let nibAttributedNormalTitle = attributedTitleForState(.Normal) {
setAttributedTitle(nibAttributedNormalTitle, forState: .Normal)
}
}
override public func setAttributedTitle(title: NSAttributedString!, forState state: UIControlState) {
super.setAttributedTitle(localizeAttributedStringByAttributesSections(title), forState: state)
updateEdgeInsets()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment