Search code examples
xcodebuttonswiftuitvosapple-tv

SwiftUI: Action of custom button not triggered


Testing some stuff on tvOS with SwiftUI. When i add a custom style to a button, the "action" of the button is not getting triggered. In this example, i wanna print "pressed", but adding functions is not working either.

Is it possible to implement an custom action trigger aswell or what am i doing wrong?

For clarification why i wanna have a custom button style.

When i dont use any buttonstyle, the "action" is working, but the "onFocusChange" function is never getting called. WHICH I NEED!

But.. when i use a buttonstyle, the onFocusChange is working but the action is not.....

struct CustomButton: View {
    @State private var buttonFocus: Bool = false
    var body: some View {
        VStack(alignment: .center){
            Button(action: {
                print("pressed")
            })
            {
                Text("Save")
            }
            .buttonStyle(TestButtonStyle(focused: buttonFocus))
            .focusable(true, onFocusChange: { (changed) in
                self.buttonFocus.toggle()
            })
        }    
    }
}

Buttonstyle:

struct TestButtonStyle: ButtonStyle {
    let focused: Bool

    public func makeBody(configuration: TestButtonStyle.Configuration) -> some View {
        configuration.label
            .foregroundColor(.white)
            .background(RoundedRectangle(cornerRadius: 5).fill(Color.red))
            .scaleEffect(focused ? 1.5 : 1.0)
    }
}

Solution

  • Its working with SwiftUI 2.0 now. You can use the following environment Object on your View you want to be focused. Also, add a State or Binding to bubble up to your parent view.

    @Environment(\.isFocused) var isFocused: Bool
    @Binding var focusedValue: Bool
    

    Then, you can call the following modifier, which gets called when the View is getting focused or not. Here you change your Binding or State variable.

    .onChange(of: isFocused, perform: { value in
            self.focusedValue = value
        })
    

    Finally, you can use your Binding or State to modify your View.

    .scaleEffect(self.focused ? 1.1 : 1)
    .animation(.linear(duration: 0.1))