Instantly share code, notes, and snippets.
Last active
May 3, 2020 07:39
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save Josscii/994088039e557b8ff9b45bd131526456 to your computer and use it in GitHub Desktop.
支持上下左右图片文字布局的 button,支持 xib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
@IBDesignable | |
class Button: UIButton { | |
enum TextPosition: Int { | |
case top | |
case left | |
case bottom | |
case right | |
} | |
@IBInspectable private var position: Int { | |
set { | |
textPosition = TextPosition(rawValue: newValue) ?? .right | |
} | |
get { | |
return textPosition.rawValue | |
} | |
} | |
var textPosition: TextPosition = .right | |
@IBInspectable var spacing: CGFloat = 0 | |
// in case frame pixel | |
func scaleFloor(_ value: CGFloat) -> CGFloat { | |
return floor(value * UIScreen.main.scale) / UIScreen.main.scale | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
if currentImage == nil { | |
return | |
} | |
if currentTitle == nil { | |
return | |
} | |
guard let titleLabel = titleLabel, let imageView = imageView else { | |
return | |
} | |
let textIntrinsicSize = titleLabel.intrinsicContentSize | |
let imageIntrinsicSize = imageView.intrinsicContentSize | |
switch textPosition { | |
case .top: | |
let textWidth = textIntrinsicSize.width | |
let textHeight = textIntrinsicSize.height | |
let imageWidth = imageIntrinsicSize.width | |
let imageHeight = imageIntrinsicSize.height | |
let totalHeight = textHeight + spacing + imageHeight | |
titleLabel.bounds.size = textIntrinsicSize | |
titleLabel.frame.origin.x = scaleFloor((bounds.width - textWidth)/2) | |
titleLabel.frame.origin.y = scaleFloor((bounds.height - totalHeight)/2) | |
imageView.bounds.size = imageIntrinsicSize | |
imageView.frame.origin.x = scaleFloor((bounds.width - imageWidth)/2) | |
imageView.frame.origin.y = scaleFloor(titleLabel.frame.maxY) + spacing | |
case .bottom: | |
let textWidth = textIntrinsicSize.width | |
let textHeight = textIntrinsicSize.height | |
let imageWidth = imageIntrinsicSize.width | |
let imageHeight = imageIntrinsicSize.height | |
let totalHeight = imageHeight + spacing + textHeight | |
imageView.bounds.size = imageIntrinsicSize | |
imageView.frame.origin.x = scaleFloor((bounds.width - imageWidth)/2) | |
imageView.frame.origin.y = scaleFloor((bounds.height - totalHeight)/2) | |
titleLabel.bounds.size = textIntrinsicSize | |
titleLabel.frame.origin.x = scaleFloor((bounds.width - textWidth)/2) | |
titleLabel.frame.origin.y = scaleFloor(imageView.frame.maxY) + spacing | |
case .left: | |
let imageWidth = imageIntrinsicSize.width | |
let imageHeight = imageIntrinsicSize.height | |
let textWidth = textIntrinsicSize.width | |
let textHeight = textIntrinsicSize.height | |
let totalWidth = textWidth + spacing + imageWidth | |
titleLabel.bounds.size = textIntrinsicSize | |
titleLabel.frame.origin.y = scaleFloor((bounds.height - textHeight)/2) | |
titleLabel.frame.origin.x = scaleFloor((bounds.width - totalWidth)/2) | |
imageView.bounds.size = imageIntrinsicSize | |
imageView.frame.origin.y = scaleFloor((bounds.height - imageHeight)/2) | |
imageView.frame.origin.x = scaleFloor(titleLabel.frame.maxX) + spacing | |
case .right: | |
let imageWidth = imageIntrinsicSize.width | |
let imageHeight = imageIntrinsicSize.height | |
let textWidth = textIntrinsicSize.width | |
let textHeight = textIntrinsicSize.height | |
let totalWidth = imageWidth + spacing + textWidth | |
imageView.bounds.size = imageIntrinsicSize | |
imageView.frame.origin.y = scaleFloor((bounds.height - imageHeight)/2) | |
imageView.frame.origin.x = scaleFloor((bounds.width - totalWidth)/2) | |
titleLabel.bounds.size = textIntrinsicSize | |
titleLabel.frame.origin.y = scaleFloor((bounds.height - textHeight)/2) | |
titleLabel.frame.origin.x = scaleFloor(imageView.frame.maxX) + spacing | |
} | |
} | |
override var intrinsicContentSize: CGSize { | |
if currentImage == nil { | |
return super.intrinsicContentSize | |
} | |
if currentTitle == nil { | |
return super.intrinsicContentSize | |
} | |
guard let titleLabel = titleLabel, let imageView = imageView else { | |
return super.intrinsicContentSize | |
} | |
let textSize = titleLabel.intrinsicContentSize | |
let imageSize = imageView.intrinsicContentSize | |
switch textPosition { | |
case .top, .bottom: | |
let width = contentEdgeInsets.left + max(textSize.width, imageSize.width) + contentEdgeInsets.right | |
let height = contentEdgeInsets.top + textSize.height + spacing + imageSize.height + contentEdgeInsets.bottom | |
return CGSize(width: width, height: height) | |
case .left, .right: | |
let height = contentEdgeInsets.top + max(textSize.height, imageSize.height) + contentEdgeInsets.bottom | |
let width = contentEdgeInsets.left + textSize.width + spacing + imageSize.width + contentEdgeInsets.right | |
return CGSize(width: width, height: height) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment