tvos: change focused color of UIButton

How to change default white color of tvos swift UIButton focus selection? override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { if let nextFocusedView = context.nextFocusedView { playAllOutlet.backgroundColor = UIColor.red shuffleBtnOutlet.backgroundColor = UIColor.green

}

if let previousFocusView = context.previouslyFocusedView {
       playAllOutlet.backgroundColor  = UIColor.red
    shuffleBtnOutlet.backgroundColor = UIColor.green
}

} But background when button is focused is still white

Post not yet marked as solved Up vote post of ashishk741 Down vote post of ashishk741
473 views

Replies

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)
    }
}