Changing the color of a Button in SwiftUI on tvOS
Again, I have only checked it on iOS, but this should help:
struct ContentView: View {
@State var selected = false
var body: some View {
Button(action: { self.selected.toggle() }) {
Text($selected.wrappedValue ? "On":"Off")
.foregroundColor(.white)
} .padding(.all)
.background(RoundedRectangle(cornerRadius: 5.0)
.fill(self.selected ? Color.green : Color.blue))
}
}
You can pass any view into .background() modifier, so you might also want to try placing an Image() in there.
How can I create a button with a background color for tvOS while still showing focus?
Override didUpdateFocusInContext
method and check if next focus view is button, if yes then customize its UI, and to set it back to orignal state check context.previousFocusedView
was that button, something like below
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
if (context.nextFocusedView == _button)
{
// set background color
}
else if (context.previousFocusedView == _button)
{
// set background color to background
}
}
In Swift (tvOS) how do you change a UIButton's highlight and focus colors?
You're definitely on the right track!
Once you subclass UIButton, you can override the function didUpdateFocusInContext
(from UIFocusEnvironment
protocol, which UIButton
on tvOS already implements)
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
if context.nextFocusedView == self {
// This is when the button will be focused
// You can change the backgroundColor and textColor here
} else {
// This is when the focus has left and goes back to default
// Don't forget to reset the values
}
}
You can also get fancy and transform the frame to imitate the default "focus" effect!
Custom Button style (SwiftUI) tvOS
Apple’s recommended solution is to use the new CardButtonStyle
button style, which removes the usual padding but keeps the tvOS hover effects:
Button(action: {}, label: {
Text("B")
.padding()
.background(Color.red)
.clipShape(Circle())
})
.buttonStyle(CardButtonStyle())
However, this still applies a round-rect button background, which doesn’t look good with your Circle background.
I’d recommend updating your design so you can use CardButtonStyle. Button manages its own focus state, so you can’t override or wire-up anything to it. And on tvOS you can’t make your own button from scratch because there is no onTap/onClick event. Your only other real option is to build a custom button in UIKit so you can avoid the limits of SwiftUI on tvOS.
Is it possible to use different colors for focused and selected state on uitabbaritems at tvOS?
I fixed that by setting the the standardAppearance
of the tab bar each time the focus changes in my UITabBarController
. The relevant code looks like this (the initial setup of appearance is only posted for completeness):
// setting up standard appearance for the first time
private func setupTabbarAppearance() {
let tabBarAppearance = UITabBarAppearance()
//...
tabBarAppearance.selectionIndicatorTintColor = .focusedBackgroundColor // focused items
//...
let itemAppearance = UITabBarItemAppearance()
//...
itemAppearance.normal.titleTextAttributes[.foregroundColor] = .normalTextColor // used for focused AND non-focused items,
// when the whole tabbar is focused
//...
itemAppearance.selected.titleTextAttributes[.foregroundColor] = .selectedTextColor // used for the selected item,
// wen tabbar is not focused
// ...
tabBarAppearance.inlineLayoutAppearance = itemAppearance
tabBar.standardAppearance = tabBarAppearance
tabBar.setNeedsLayout()
}
private func setTabBarIndicatorColor(tabBarFocused: Bool) {
let currentAppearance = tabBar.standardAppearance
// here is where the color is set
currentAppearance.selectionIndicatorTintColor = tabBarFocused ? .focusedBackgroundColor : .selectedBackgroundColor
tabBar.standardAppearance = currentAppearance
}
// change appearance each time, when focus changes in tabbar controller
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
if isTabbarInHierarchy(view: context.nextFocusedView) {
setTabBarIndicatorColor(tabBarFocused: true)
} else {
setTabBarIndicatorColor(tabBarFocused: false)
}
super.didUpdateFocus(in: context, with: coordinator)
}
private func isTabbarInHierarchy(view: UIView?) -> Bool {
guard let view = view else {return false}
if view == tabBar {
return true
}
return isTabbarInHierarchy(view: view.superview)
}
How to create a UIButton for tvOS with a clear background color?
Since tvOS 11 there is a solution for that using the button type "plain" instead of "system" without loosing the effects for focusing and selection:
Open the button properties in the Interface builder an select "Type"->"Plain"
Set the button background color to "clear color"
Thats it.
Watch Apples Video about "UIButtonTypePlain" here (starts at 13:44):
UIButtonTypePlain explained
How to set custom highlighted state of SwiftUI Button
Updated for SwiftUI beta 5
SwiftUI does actually expose an API for this: ButtonStyle
.
struct MyButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.padding()
.foregroundColor(.white)
.background(configuration.isPressed ? Color.red : Color.blue)
.cornerRadius(8.0)
}
}
// To use it
Button(action: {}) {
Text("Hello World")
}
.buttonStyle(MyButtonStyle())
Related Topics
Saving Coredata to a Web Server with Swift 3.0
Solving System of Equations in Swift
How to Make a Segue to Second Item of Tab Bar
Error "No Such Module" When Installed Framework with Pod in Swift 3
Swift:Pause and Resume Nstimer
JSONserialization.JSONobject Performance in Swift
How to Cancel Firebase Setvalue While Pending for Completion (When Offline)
Color Keying Video with Gpuimage on a Scnplane in Arkit
Loading Multiple Google Interstitial Ads Makes App Crash
Appdelegate Segue Alternative Pass Data
Best Way to Structure My Firebase Database
Dynamically Call a Function in Swift
Fetching Child Sum from Core Data
How to Make a Custom Geometryreader in Swiftui
How to Use Multiple Mtlrenderpipelinestates in One Mtlrendercommandencoder