Skip to content

Commit

Permalink
NKButtonStack supports border and shadow
Browse files Browse the repository at this point in the history
  • Loading branch information
kennic committed Oct 27, 2021
1 parent aed07c2 commit 1c09e11
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 4 deletions.
8 changes: 7 additions & 1 deletion Example/NKButton/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,15 @@ class ViewController: UIViewController {
// Example of NKButtonStack usage:

let buttonStack = NKButtonStack<NKButton>()
buttonStack.backgroundColor = .systemRed
buttonStack.borderSize = 2
buttonStack.borderColor = .systemRed
buttonStack.shadowColor = .gray
buttonStack.shadowRadius = 4
buttonStack.shadowOpacity = 1.0

buttonStack.configurationBlock = { (button, item, index) in
button.backgroundColors[.normal] = .brown
button.backgroundColors[.normal] = .lightGray
button.backgroundColors[.highlighted] = .gray
button.backgroundColors[.selected] = .red
button.backgroundColors[[.selected, .highlighted]] = .green
Expand Down
2 changes: 1 addition & 1 deletion NKButton.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'NKButton'
s.version = '4.5'
s.version = '4.6'
s.summary = 'A fully customizable UIButton'
s.description = <<-DESC
A fully customizable button that fills all lacked functions from UIButton like:
Expand Down
128 changes: 126 additions & 2 deletions NKButton/Classes/NKButtonStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,75 @@ open class NKButtonStack<T: UIButton>: UIControl {

open var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
if (cornerRadius > 0) { layer.masksToBounds = true }
guard cornerRadius != oldValue else { return }
setNeedsDisplay()
}
}

/** Shadow color */
open var shadowColor: UIColor? = nil {
didSet {
guard shadowColor != oldValue else { return }
setNeedsDisplay()
}
}

/** Shadow radius */
open var shadowRadius: CGFloat = 0 {
didSet {
guard shadowRadius != oldValue else { return }
setNeedsDisplay()
}
}

/** Shadow opacity */
open var shadowOpacity: Float = 0.5 {
didSet {
guard shadowOpacity != oldValue else { return }
setNeedsDisplay()
}
}

/** Shadow offset */
open var shadowOffset: CGSize = .zero {
didSet {
guard shadowOffset != oldValue else { return }
setNeedsDisplay()
}
}

/** Border color */
open var borderColor: UIColor? = nil {
didSet {
guard borderColor != oldValue else { return }
setNeedsDisplay()
}
}

/** Size of border */
open var borderSize: CGFloat = 0 {
didSet {
guard borderSize != oldValue else { return }
setNeedsDisplay()
}
}

/** Border dash pattern */
open var borderDashPattern: [NSNumber]? = nil {
didSet {
guard borderDashPattern != oldValue else { return }
setNeedsDisplay()
}
}

/** Border color */
private var _backgroundColor: UIColor? = nil
open override var backgroundColor: UIColor?{
get { _backgroundColor }
set {
_backgroundColor = newValue
setNeedsDisplay()
super.backgroundColor = .clear
}
}

Expand Down Expand Up @@ -136,6 +203,9 @@ open class NKButtonStack<T: UIButton>: UIControl {
public let scrollView = UIScrollView()
public let frameLayout = StackFrameLayout(axis: .horizontal, distribution: .equal)

fileprivate let shadowLayer = CAShapeLayer()
fileprivate let backgroundLayer = CAShapeLayer()

// MARK: -

convenience public init(items: [NKButtonItem], axis: NKLayoutAxis = .horizontal) {
Expand All @@ -150,6 +220,9 @@ open class NKButtonStack<T: UIButton>: UIControl {
public init() {
super.init(frame: .zero)

layer.addSublayer(shadowLayer)
layer.addSublayer(backgroundLayer)

frameLayout.spacing = 1.0
frameLayout.isIntrinsicSizeEnabled = true
frameLayout.shouldCacheSize = false
Expand All @@ -174,9 +247,44 @@ open class NKButtonStack<T: UIButton>: UIControl {
return frameLayout.sizeThatFits(size)
}

override open func draw(_ rect: CGRect) {
super.draw(rect)

let backgroundFrame = bounds
let fillColor = backgroundColor
let strokeColor = borderColor
let strokeSize = borderSize
let roundedPath = UIBezierPath(roundedRect: backgroundFrame, cornerRadius: cornerRadius)
let path = roundedPath.cgPath

backgroundLayer.path = path
backgroundLayer.fillColor = fillColor?.cgColor
backgroundLayer.strokeColor = strokeColor?.cgColor
backgroundLayer.lineWidth = strokeSize
backgroundLayer.miterLimit = roundedPath.miterLimit
backgroundLayer.lineDashPattern = borderDashPattern

if let shadowColor = shadowColor {
shadowLayer.isHidden = false
shadowLayer.path = path
shadowLayer.shadowPath = path
shadowLayer.fillColor = shadowColor.cgColor
shadowLayer.shadowColor = shadowColor.cgColor
shadowLayer.shadowRadius = shadowRadius
shadowLayer.shadowOpacity = shadowOpacity
shadowLayer.shadowOffset = shadowOffset
}
else {
shadowLayer.isHidden = true
}
}

override open func layoutSubviews() {
super.layoutSubviews()

shadowLayer.frame = bounds
backgroundLayer.frame = bounds

let viewSize = bounds.size
let contentSize = frameLayout.sizeThatFits(CGSize(width: CGFloat.infinity, height: CGFloat.infinity))
scrollView.contentSize = contentSize
Expand All @@ -201,6 +309,15 @@ open class NKButtonStack<T: UIButton>: UIControl {
cornerRadius = viewSize.height / 2
setNeedsDisplay()
}

if cornerRadius > 0 {
scrollView.layer.cornerRadius = cornerRadius
scrollView.layer.masksToBounds = true
}
else {
scrollView.layer.cornerRadius = 0
scrollView.layer.masksToBounds = false
}
}

// MARK: -
Expand All @@ -209,6 +326,13 @@ open class NKButtonStack<T: UIButton>: UIControl {
return frameLayout.frameLayout(at: index)?.targetView as? T
}

open func setShadow(color: UIColor?, radius: CGFloat, opacity: Float = 1.0, offset: CGSize = .zero) {
self.shadowColor = color
self.shadowOpacity = opacity
self.shadowRadius = radius
self.shadowOffset = offset
}

// MARK: -

fileprivate func updateLayout() {
Expand Down

0 comments on commit 1c09e11

Please sign in to comment.