I am aware that I can change the background color of a Toggle using .tint()
. However, my toggle background can be yellow or similar (light) colors, which doesn’t look good with the default white thumb.
Here is how it looks:
Off mode looks good though, so that is no issue:
How can I change the thumb color in SwiftUI so that it looks good with different background colors?
For now, you can only change the thumb color through UISwitch.thumbTintColor
. Here is a modified version of this answer that allows you to pass in a color for thumbTintColor
, in addition to onTintColor
.
public struct ColoredSwitch<Label>: View where Label: View {
@Binding var isOn: Bool
var thumbTintColor: Color
var onTintColor: Color
var label: Label
public init(isOn: Binding<Bool>, thumbTintColor: Color, onTintColor: Color, @ViewBuilder label: () -> Label) {
self._isOn = isOn
self.label = label()
self.thumbTintColor = thumbTintColor
self.onTintColor = onTintColor
}
public var body: some View {
LabeledContent {
UISwitchWrapper(isOn: $isOn, thumbTintColor: thumbTintColor, onTintColor: onTintColor)
} label: {
label
}
}
}
struct UISwitchWrapper: UIViewRepresentable {
@Binding var isOn: Bool
var thumbTintColor: Color
var onTintColor: Color
public func makeUIView(context: Context) -> UISwitch {
let uiSwitch = UISwitch()
uiSwitch.addTarget(
context.coordinator,
action: #selector(Coordinator.valueChanged(_:)),
for: .valueChanged
)
return uiSwitch
}
public func updateUIView(_ uiView: UISwitch, context: Context) {
uiView.setOn(isOn, animated: !context.transaction.disablesAnimations)
uiView.thumbTintColor = UIColor(thumbTintColor)
uiView.onTintColor = UIColor(onTintColor)
context.coordinator.parent = self
}
public func makeCoordinator() -> Coordinator {
Coordinator(self)
}
@MainActor
public class Coordinator: NSObject {
var parent: UISwitchWrapper
init(_ parent: UISwitchWrapper) {
self.parent = parent
}
@objc
func valueChanged(_ sender: UISwitch) {
parent.isOn = sender.isOn
}
}
}
Example usage:
@State private var isOn = false
var body: some View {
ColoredSwitch(isOn: $isOn, thumbTintColor: .blue, onTintColor: .yellow) {
Text("Some Label")
}
}