2025-04-16 18:22:12 +08:00

219 lines
6.9 KiB
Swift

//
// JXButton.swift
// BoJia
//
// Created by on 2024/5/31.
//
import UIKit
class JXButton: UIButton {
lazy var jx_font: UIFont? = self.titleLabel?.font {
didSet {
self.titleLabel?.font = jx_font
}
}
var maxTitleWidth: CGFloat = 0
var titleDirection: UITextLayoutDirection?
///
var leftAnyRightmargin: CGFloat = 0
///
var space: CGFloat = 0
private var imageRect: CGRect = .zero
private var titleRect: CGRect = .zero
override func layoutSubviews() {
super.layoutSubviews()
}
override var intrinsicContentSize: CGSize {
var width: CGFloat = 0
var height: CGFloat = 0
switch titleDirection {
case .left:
width = imageRect.width + titleRect.width + space
if imageRect.height > titleRect.height {
height = imageRect.height
} else {
height = titleRect.height
}
case .up:
if imageRect.width > titleRect.width {
width = imageRect.width
} else {
width = titleRect.width
}
height = titleRect.height + imageRect.height + space
case .down:
if imageRect.width > titleRect.width {
width = imageRect.width
} else {
width = titleRect.width
}
height = titleRect.height + imageRect.height + space
default:
width = imageRect.width + titleRect.width + space
if imageRect.height > titleRect.height {
height = imageRect.height
} else {
height = titleRect.height
}
}
let size = CGSize(width: width + leftAnyRightmargin * 2, height: height)
return size
}
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
let imageSize = currentImage?.size ?? .zero
let textSize = self._textSize()
let contentWidth = self.frame.size.width
let contentHeight = self.frame.size.height
var x: CGFloat = 0
var y: CGFloat = 0
var width: CGFloat = 0
var height: CGFloat = 0
switch titleDirection {
case .left:
x = (contentWidth - space) / 2 - imageSize.width / 2 + textSize.width / 2 + space
y = contentHeight / 2 - imageSize.height / 2
width = imageSize.width
height = imageSize.height
case .up:
x = contentWidth / 2 - imageSize.width / 2
y = (contentHeight - space) / 2 - imageSize.height / 2 + textSize.height / 2 + space
width = imageSize.width
height = imageSize.height
case .down:
x = contentWidth / 2 - imageSize.width / 2
y = (contentHeight - space) / 2 - imageSize.height / 2 - textSize.height / 2
width = imageSize.width
height = imageSize.height
default:
x = (contentWidth - space) / 2 - imageSize.width / 2 - textSize.width / 2
y = contentHeight / 2 - imageSize.height / 2
width = imageSize.width
height = imageSize.height
}
self.imageRect = CGRect(x: x, y: y, width: width, height: height)
return self.imageRect
}
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let imageSize = currentImage?.size ?? .zero
let textSize = self._textSize()
let contentWidth = self.frame.size.width
let contentHeight = self.frame.size.height
var x: CGFloat = 0
var y: CGFloat = 0
var width: CGFloat = 0
var height: CGFloat = 0
switch titleDirection {
case .left:
x = (contentWidth - space) / 2 - imageSize.width / 2 - textSize.width / 2
y = contentHeight / 2 - textSize.height / 2
width = textSize.width
height = textSize.height
case .up:
x = contentWidth / 2 - textSize.width / 2
y = (contentHeight - space) / 2 - textSize.height / 2 - imageSize.height / 2
width = textSize.width
height = textSize.height
case .down:
x = contentWidth / 2 - textSize.width / 2
y = (contentHeight - space) / 2 - textSize.height / 2 + imageSize.height / 2 + space
width = textSize.width
height = textSize.height
default:
x = (contentWidth - space) / 2 + imageSize.width / 2 - textSize.width / 2 + space
y = contentHeight / 2 - textSize.height / 2
width = textSize.width
height = textSize.height
}
self.titleRect = CGRect(x: x, y: y, width: width, height: height)
return self.titleRect
}
private var borderColors: [UInt : UIColor] = [:]
func jx_setBorderColor(_ color: UIColor?, for state: UIControl.State) {
var arr = self.borderColors
let index = state.rawValue
arr[index] = color
if state == .selected {
let i = index + UIControl.State.highlighted.rawValue
arr[i] = color
}
self.borderColors = arr
updateStatus()
}
func updateStatus() {
var color = self.borderColors[self.state.rawValue]?.cgColor
if (color == nil) {
color = self.borderColors[UIControl.State.normal.rawValue]?.cgColor
}
self.layer.borderColor = color
}
override var isSelected: Bool {
didSet {
updateStatus()
}
}
}
extension JXButton {
private func _textSize() -> CGSize {
// let size = CGSize(width: self.bounds.size.width, height: self.bounds.size.height)
var attr: [NSAttributedString.Key : Any] = [:]
attr[NSAttributedString.Key.font] = jx_font
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingMiddle
attr[NSAttributedString.Key.paragraphStyle] = paragraphStyle
// var rect = self.currentTitle?.ocString.boundingRect(with: size, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attr, context: nil) ?? .zero
if let font = jx_font {
var size = self.currentTitle?.size(font: font) ?? .zero
if maxTitleWidth != 0 && maxTitleWidth < size.width {
size = CGSize(width: maxTitleWidth, height: size.height)
}
// if maxTitleWidth != 0 && maxTitleWidth < rect.size.width {
// rect.size = CGSize(width: maxTitleWidth, height: rect.size.height)
// }
return size
} else {
return .zero
}
}
}