Post

Replies

Boosts

Views

Activity

Reply to tvos: change focused color of UIButton
Hello, I was also struggling a bit with tvos default focus color. The only solution I came up with was to use basic UIButton() initializer. If you use, for example, UIButton(type: .plain), white color will always be on top of your background color. The problem with this approach is that you lose the default parallax effect. I worked around this issue by implementing a custom logic for increasing button size when focused. It's a bit hacky solution, but I hope it helps you. Here is an example how you can code it: import UIKit struct ColorConfiguration { var defaultBackgroundColor: UIColor var defaultTintColor: UIColor var focusedBackgroundColor: UIColor var focusedTintColor: UIColor static let exampleColors1 = ColorConfiguration( defaultBackgroundColor: .blue, defaultTintColor: .white, focusedBackgroundColor: .yellow, focusedTintColor: .black) static let exampleColors2 = ColorConfiguration( defaultBackgroundColor: .red, defaultTintColor: .gray, focusedBackgroundColor: .green, focusedTintColor: .white) } class CustomFocusColorButton: UIButton { private let focusedScale: CGFloat = 1.05 private let colorConfig: ColorConfiguration init(colorConfig: ColorConfiguration) { self.colorConfig = colorConfig super.init(frame: .zero) layer.cornerRadius = 10 backgroundColor = colorConfig.defaultBackgroundColor setTitleColor(colorConfig.defaultTintColor, for: .normal) tintColor = colorConfig.defaultTintColor } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { super.pressesBegan(presses, with: event) guard presses.first?.type == .select else { return } UIView.animate(withDuration: 0.1) { self.transform = .identity } } override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) { super.pressesEnded(presses, with: event) UIView.animate(withDuration: 0.1) { if self.isFocused { self.transform = CGAffineTransform(scaleX: self.focusedScale, y: self.focusedScale) } else { self.transform = .identity } } } override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { super.didUpdateFocus(in: context, with: coordinator) if context.nextFocusedView == self { coordinator.addCoordinatedAnimations { self.backgroundColor = self.colorConfig.focusedBackgroundColor self.setTitleColor(self.colorConfig.focusedTintColor, for: .normal) self.tintColor = self.colorConfig.focusedTintColor self.transform = CGAffineTransform(scaleX: self.focusedScale, y: self.focusedScale) } } else { coordinator.addCoordinatedAnimations { self.backgroundColor = self.colorConfig.defaultBackgroundColor self.setTitleColor(self.colorConfig.defaultTintColor, for: .normal) self.tintColor = self.colorConfig.defaultTintColor self.transform = .identity } } } } import UIKit class TestViewController: UIViewController { let button1 = CustomFocusColorButton(colorConfig: .exampleColors1) let button2 = CustomFocusColorButton(colorConfig: .exampleColors2) override func viewDidLoad() { super.viewDidLoad() view.addSubview(button1) button1.translatesAutoresizingMaskIntoConstraints = false button1.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true button1.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -100).isActive = true button1.widthAnchor.constraint(equalToConstant: 200).isActive = true button1.heightAnchor.constraint(equalToConstant: 80).isActive = true view.addSubview(button2) button2.translatesAutoresizingMaskIntoConstraints = false button2.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true button2.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true button2.widthAnchor.constraint(equalToConstant: 200).isActive = true button2.heightAnchor.constraint(equalToConstant: 80).isActive = true button1.setTitle("Button 1", for: .normal) button2.setTitle("Button 2", for: .normal) } }
Feb ’24