| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- //
- // ButtonWithImageAndTitleExtension.swift
- // ButtonWithImageAndTitleDemo
- //
- // Created by Mervyn Ong on 24/10/14.
- // Copyright (c) 2014 mervynokm. All rights reserved.
- //
- //
- // The MIT License (MIT)
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- import UIKit
- @objc extension UIButton {
- /// Enum to determine the title position with respect to the button image
- ///
- /// - top: title above button image
- /// - bottom: title below button image
- /// - left: title to the left of button image
- /// - right: title to the right of button image
- @objc enum Position: Int {
- case top, bottom, left, right
- }
-
- /// This method sets an image and title for a UIButton and
- /// repositions the titlePosition with respect to the button image.
- ///
- /// - Parameters:
- /// - image: Button image
- /// - title: Button title
- /// - titlePosition: UIViewContentModeTop, UIViewContentModeBottom, UIViewContentModeLeft or UIViewContentModeRight
- /// - additionalSpacing: Spacing between image and title
- /// - state: State to apply this behaviour
- @objc func set(image: UIImage?, title: String, titlePosition: Position, additionalSpacing: CGFloat, state: UIControl.State){
- imageView?.contentMode = .center
- setImage(image, for: state)
- setTitle(title, for: state)
- titleLabel?.contentMode = .center
- adjust(title: title as NSString, at: titlePosition, with: additionalSpacing)
-
- }
-
- /// This method sets an image and an attributed title for a UIButton and
- /// repositions the titlePosition with respect to the button image.
- ///
- /// - Parameters:
- /// - image: Button image
- /// - title: Button attributed title
- /// - titlePosition: UIViewContentModeTop, UIViewContentModeBottom, UIViewContentModeLeft or UIViewContentModeRight
- /// - additionalSpacing: Spacing between image and title
- /// - state: State to apply this behaviour
- @objc func set(image: UIImage?, attributedTitle title: NSAttributedString, at position: Position, width spacing: CGFloat, state: UIControl.State){
- imageView?.contentMode = .center
- setImage(image, for: state)
-
- adjust(attributedTitle: title, at: position, with: spacing)
-
- titleLabel?.contentMode = .center
- setAttributedTitle(title, for: state)
- }
-
-
- // MARK: Private Methods
-
- @objc private func adjust(title: NSString, at position: Position, with spacing: CGFloat) {
- let imageRect: CGRect = self.imageRect(forContentRect: frame)
-
- // Use predefined font, otherwise use the default
- let titleFont: UIFont = titleLabel?.font ?? UIFont()
- let titleSize: CGSize = title.size(withAttributes: [NSAttributedString.Key.font: titleFont])
-
- arrange(titleSize: titleSize, imageRect: imageRect, atPosition: position, withSpacing: spacing)
- }
-
- @objc private func adjust(attributedTitle: NSAttributedString, at position: Position, with spacing: CGFloat) {
- let imageRect: CGRect = self.imageRect(forContentRect: frame)
- let titleSize = attributedTitle.size()
-
- arrange(titleSize: titleSize, imageRect: imageRect, atPosition: position, withSpacing: spacing)
- }
- @objc private func arrange(titleSize: CGSize, imageRect:CGRect, atPosition position: Position, withSpacing spacing: CGFloat) {
- switch (position) {
- case .top:
- titleEdgeInsets = UIEdgeInsets(top: -(imageRect.height + titleSize.height + spacing), left: -(imageRect.width), bottom: 0, right: 0)
- imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -titleSize.width)
- contentEdgeInsets = UIEdgeInsets(top: spacing / 2 + titleSize.height, left: -imageRect.width/2, bottom: 0, right: -imageRect.width/2)
- case .bottom:
- titleEdgeInsets = UIEdgeInsets(top: (imageRect.height + titleSize.height + spacing), left: -(imageRect.width), bottom: 0, right: 0)
- imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -titleSize.width)
- contentEdgeInsets = UIEdgeInsets(top: 0, left: -imageRect.width/2, bottom: spacing / 2 + titleSize.height, right: -imageRect.width/2)
- case .left:
- titleEdgeInsets = UIEdgeInsets(top: 0, left: -(imageRect.width * 2), bottom: 0, right: 0)
- imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -(titleSize.width * 2 + spacing))
- contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: spacing / 2)
- case .right:
- titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -spacing)
- imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
- contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: spacing / 2)
- }
- }
- }
|