Skip to content

Instantly share code, notes, and snippets.

@maakcode
Last active March 24, 2022 23:02
Show Gist options
  • Save maakcode/95ed4f8be8a3738730b449e9ce0054f9 to your computer and use it in GitHub Desktop.
Save maakcode/95ed4f8be8a3738730b449e9ce0054f9 to your computer and use it in GitHub Desktop.
How to set UIButton background color for control state with single dynamic color
import UIKit
extension UIButton {
func setBackgroundColor(_ color: UIColor, for state: State) {
let backgroundImage: UIImage = .dynamicImage(light: .generate(withColor: color.light),
dark: .generate(withColor: color.dark))
setBackgroundImage(backgroundImage, for: state)
}
}
/// https://stackoverflow.com/a/63928952/12353435
extension UIImage {
static func generate(withColor color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContext(rect.size)
if let context = UIGraphicsGetCurrentContext() {
context.setFillColor(color.cgColor)
context.fill(rect)
}
let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
UIGraphicsEndImageContext()
return image
}
static func dynamicImage(light: @autoclosure () -> UIImage, dark: @autoclosure () -> UIImage) -> UIImage {
if #available(iOS 13.0, *) {
var lightImage = UIImage()
var darkImage = UIImage()
let lightTraitCollection = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .light)])
lightTraitCollection.performAsCurrent {
lightImage = light()
}
let darkTraitCollection = UITraitCollection(traitsFrom: [.current, .init(userInterfaceStyle: .dark)])
darkTraitCollection.performAsCurrent {
darkImage = dark()
}
lightImage.imageAsset?.register(darkImage, with: darkTraitCollection)
return lightImage
}
else {
return light()
}
}
}
/// https://stackoverflow.com/a/65494068/12353435
extension UIColor {
var dark: UIColor { resolvedColor(with: .init(userInterfaceStyle: .dark)) }
var light: UIColor { resolvedColor(with: .init(userInterfaceStyle: .light)) }
}
final class ViewController: UIViewController {
lazy var button: UIButton = {
let view = UIButton(type: .custom)
let disabledColor = UIColor {
$0.userInterfaceStyle == .dark ? UIColor.darkGray : UIColor.lightGray
}
view.setBackgroundColor(disabledColor, for: .disabled)
view.setTitle("Normal", for: .normal)
view.setTitle("Disabled", for: .disabled)
view.setTitleColor(.label, for: .normal)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
/// Shake the device to toggle the button status
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
super.motionEnded(motion, with: event)
guard motion == .motionShake else { return }
button.isEnabled.toggle()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment