Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for background views #24

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion SimpleButton/SimpleButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ import UIKit
open class SimpleButton: UIButton {

typealias ControlState = UInt

/// Background view.
open var backgroundView: UIView? {
didSet {
if let backgroundView = backgroundView {
backgroundView.isUserInteractionEnabled = false
addSubview(backgroundView)
sendSubview(toBack: backgroundView)
constrainFill(backgroundView)
}
}
}

/// Loading view. UIActivityIndicatorView as default
open var loadingView: UIView?
Expand Down Expand Up @@ -39,6 +51,13 @@ open class SimpleButton: UIButton {
}

// MARK: State values with initial values
fileprivate lazy var backgroundViews: [ControlState: SimpleButtonStateChangeValue<UIView>] = {
if let view = self.backgroundView {
return [UIControlState.normal.rawValue: SimpleButtonStateChangeValue(value: view, animated: true, animationDuration: self.defaultAnimationDuration)]
}
return [:]
}()

fileprivate lazy var backgroundColors: [ControlState: SimpleButtonStateChangeValue<CGColor>] = {
if let color = self.backgroundColor?.cgColor {
return [UIControlState.normal.rawValue: SimpleButtonStateChangeValue(value: color, animated: true, animationDuration: self.defaultAnimationDuration)]
Expand Down Expand Up @@ -196,6 +215,21 @@ open class SimpleButton: UIButton {
buttonScales[state.rawValue] = SimpleButtonStateChangeValue(value: scale, animated: animated, animationDuration: animationDuration ?? self.defaultAnimationDuration)
updateScale()
}


/**
Sets the background view for a specific `UIControlState`

- parameter view: background view of button
- parameter state: determines at which state that background view applies
- parameter animated: determines if that change in background view should animate. Default is `true`
- parameter animationDuration: set this value if you need a specific animation duration for this specific state change. If this is nil, the animation duration is taken from `defaultAnimationDuration`
*/
open func setBackgroundView(_ view: UIView, for state: UIControlState = .normal, animated: Bool = true, animationDuration: TimeInterval? = nil) {
backgroundViews[state.rawValue] = SimpleButtonStateChangeValue(value: view, animated: animated, animationDuration: animationDuration ?? self.defaultAnimationDuration)
updateBackgroundView()
}


/**
Sets the background color for a specific `UIControlState`
Expand Down Expand Up @@ -319,6 +353,7 @@ open class SimpleButton: UIButton {
- parameter lockAnimatedUpdate: set this to true to update without animation, even it´s defined in `SimpleButtonStateChange`. Used to set initial button attributes
*/
fileprivate func update() {
updateBackgroundView()
updateBackgroundColor()
updateBorderColor()
updateBorderWidth()
Expand Down Expand Up @@ -347,6 +382,16 @@ open class SimpleButton: UIButton {
(stateChange.animated) && !lockAnimatedUpdate ? UIView.animate(withDuration: stateChange.animationDuration, animations: animations) : animations()
}
}

fileprivate func updateBackgroundView() {
if let stateChange = backgroundViews[state.rawValue] ?? backgroundViews[UIControlState.normal.rawValue], backgroundView == nil || backgroundView != stateChange.value {
if stateChange.animated && !lockAnimatedUpdate {
animate(layer: layer, from: sourceLayer.backgroundColor, to: stateChange.value, forKey: "backgroundView", duration: stateChange.animationDuration)
}
backgroundView?.removeFromSuperview()
backgroundView = stateChange.value
}
}

fileprivate func updateBackgroundColor() {
if let stateChange = backgroundColors[state.rawValue] ?? backgroundColors[UIControlState.normal.rawValue], layer.backgroundColor == nil || UIColor(cgColor: layer.backgroundColor!) != UIColor(cgColor: stateChange.value) {
Expand Down Expand Up @@ -421,11 +466,17 @@ open class SimpleButton: UIButton {
animation.duration = duration
layer.add(animation, forKey: key)
}

// MARK: Layout
override open func layoutSubviews() {
super.layoutSubviews()
loadingView?.center = CGPoint(x: bounds.size.width / 2,
y: bounds.size.height / 2)
}

fileprivate func constrainFill(_ view: UIView) {
view.translatesAutoresizingMaskIntoConstraints = false
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))
}
}