在SwiftUI中设置切换颜色

在SwiftUI中设置切换颜色,swift,toggle,swiftui,Swift,Toggle,Swiftui,我在遵循苹果的做法后实现了一个切换。目前看起来是这样的: 这是生成此UI的代码: NavigationView { List { Toggle(isOn: $showFavoritesOnly) { Text("Show Favorites only") } } } 现在,我希望开关的颜色是蓝色而不是绿色。 我试过: 这些都不起作用,我也找不到任何其他修改器,比如tintColor 如何更改切换的颜色?我还没有找到直接更

我在遵循苹果的做法后实现了一个切换。目前看起来是这样的:

这是生成此UI的代码:

NavigationView {
    List {
        Toggle(isOn: $showFavoritesOnly) {
            Text("Show Favorites only")
        }
    }
}
现在,我希望
开关的颜色是蓝色而不是绿色。
我试过:

这些都不起作用,我也找不到任何其他修改器,比如
tintColor


如何更改
切换
的颜色?

我还没有找到直接更改
切换
颜色的方法,但是使用蓝色开关或任何其他自定义视图的另一种方法是创建自己的自定义视图。要以最简单的形式制作自定义蓝色切换,请执行以下操作:

struct BlueToggle : UIViewRepresentable {
  func makeUIView(context: Context) -> UISwitch {
    UISwitch()
  }

  func updateUIView(_ uiView: UISwitch, context: Context) {
    uiView.onTintColor = UIColor.blue
  }
}

struct ContentView : View {
    var body: some View {
      BlueToggle()
    }
}
结果:


只需使用
UIAppearance
API:

UISwitch.appearance().onTintColor = UIColor.blue
根据
UIAppearance
文档,默认情况下,它将更改
UISwitch
的所有实例的外观

注:从Xcode 11 beta 5开始测试。

这(目前为Xcode 11 beta 6)是一个解决方案。要在选项之间切换,快速方法是使用布尔值而不是if/else:

showFavoritesOnly ? .red : .blue
对于前台:

Toggle(isOn: $showGreeting) {
  Text("Show Favorites only").foregroundColor(showFavoritesOnly ? .blue : .gray)
}
对于色调:

uiView.onTintColor = showFavoritesOnly ? UIColor.blue : UIColor.gray
除自定义颜色外:

SwiftUI 2.0 使用切换样式 现在,您可以仅在Swift 2.0中为打开位置设置色调颜色:

Toggle(isOn: $isToggleOn) {
    Text("Red")
    Image(systemName: "paintpalette")
}
.toggleStyle(SwitchToggleStyle(tint: Color.red))

Toggle(isOn: $isToggleOn) {
    Text("Orange")
    Image(systemName: "paintpalette")
}
.toggleStyle(SwitchToggleStyle(tint: Color.orange))

迅捷1.0 使用切换样式 我创建了一个新的ToggleStyle来更改切换的三种颜色(on color、off color和thumb)

使用示例 从SwiftUI手册

您可以修改init()中所有UISwitch对象的全局onTintColor


在@mohammad reza farahani的解决方案的基础上,这里提供了一种完全不妥协的方法,通过SwiftUI的实现协议实现UISwitch的可配置性

首先将
ui开关
包装在
ui视图可表示的
中,并根据需要设置颜色:

final类CustomToggleWrapper:UIViewRepresentable{
变量:绑定
初始化(isOn:绑定){
self.isOn=isOn
}
func makeUIView(上下文:context)->UISwitch{
UISwitch()
}
func updateUIView(uiView:UISwitch,context:context){
//论色彩
uiView.onTintColor=UIColor.blue
//色差
uiView.tintColor=UIColor.red
uiView.layer.cornerRadius=uiView.frame.height/2
uiView.backgroundColor=UIColor.red
uiView.isOn=isOn.wrappedValue
//更新边界布尔
uiView.addTarget(self,action:#选择器(switchIsChanged(:)),for:.valueChanged)
}
@objc
func开关已更改(\发送方:UISwitch){
isOn.wrappedValue=sender.isOn
}
}
其次,使用包装的
ui开关创建一个:

struct CustomToggleStyle:ToggleStyle{
func makeBody(配置:Self.configuration)->一些视图{
let toggle=CustomToggleWrapper(isOn:configuration.$isOn)
回钉{
配置标签
垫片()
切换
}
}
}
像平常一样执行
切换
,并应用
自定义切换样式

struct TestView:View{
@国家私有变量:Bool=true
var body:一些观点{
拨动(
伊森:伊森
) {
文本(“测试:\(字符串(isOn))”)
}.toggleStyle(CustomToggleStyle()).padding()
}
}

由于最初的问题只是改变颜色切换,而不是完全的
切换
视觉定制,我认为这样做可以:

import SwiftUI

struct CustomToggle: UIViewRepresentable {
  @Binding var isOn: Bool

  func makeCoordinator() -> CustomToggle.Coordinator {
    Coordinator(isOn: $isOn)
  }

  func makeUIView(context: Context) -> UISwitch {
    let view = UISwitch()
    view.onTintColor = UIColor.red
    view.addTarget(context.coordinator, action: #selector(Coordinator.switchIsChanged(_:)), for: .valueChanged)

    return view
  }

  func updateUIView(_ uiView: UISwitch, context: Context) {
    uiView.isOn = isOn
  }

  class Coordinator: NSObject {
    @Binding private var isOn: Bool

    init(isOn: Binding<Bool>) {
      _isOn = isOn
    }

    @objc func switchIsChanged(_ sender: UISwitch) {
      _isOn.wrappedValue = sender.isOn
    }
  }
}

// MARK: - Previews

struct CustomToggle_Previews: PreviewProvider {
  static var previews: some View {
    ViewWrapper()
  }

  struct ViewWrapper: View {
    @State(initialValue: false) var isOn: Bool

    var body: some View {
      CustomToggle(isOn: $isOn)
        .previewLayout(.fixed(width: 100, height: 100))
    }
  }
}
导入快捷界面
结构CustomToggle:UIViewRepresentable{
@绑定变量:Bool
func makeCoordinator()->CustomToggle.Coordinator{
协调员(国际部队:国际部队)
}
func makeUIView(上下文:context)->UISwitch{
let view=UISwitch()
view.onTintColor=UIColor.red
view.addTarget(context.coordinator,action:#选择器(coordinator.switchIsChanged(:)),for:.valueChanged)
返回视图
}
func updateUIView(uiView:UISwitch,context:context){
uiView.isOn=isOn
}
类协调器:NSObject{
@绑定私有变量:Bool
初始化(isOn:绑定){
_伊森
}
@objc func开关已更改(\发送方:UISwitch){
_isOn.wrappedValue=sender.isOn
}
}
}
//马克:-预览
结构CustomToggle_预览:PreviewProvider{
静态var预览:一些视图{
ViewWrapper()
}
结构视图包装器:视图{
@状态(初始值:false)变量:Bool
var body:一些观点{
自定义切换(isOn:$isOn)
.previewLayout(.fixed(宽:100,高:100))
}
}
}

Karol Kulesza和George Valkov提供了一个非常易于实施的解决方案。我只是想补充一点,您也可以将下面的代码放在app委托的didfishLaunching方法中

UISwitch.appearance().onTintColor = .blue
还可以使用创建更具体的外观配置

appearance(whenContainedInInstancesOf:)
参见

SwiftUI 2.0(WWDC-2020后) 使用新的SwiftUI增强功能,您可以使用
.toggleStyle
修改器

// Switch tinting

Toggle(isOn: $order.notifyWhenReady) {
    Text("Send notification when ready")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))

请注意,这仅适用于iOS14/iPadOS14/macOS11及以上版本。

谢谢。我将等待接受答案,看看是否会出现另一个答案。如何将此自定义切换与init
toggle
具有的相同init:
init(isOn:Binding,label:()->label)
?@LinusGeffarth一起使用,我认为还需要使用
UIViewControllerRepresentable
。检查这个例子:这并不是你所要求的,但它是处理自定义视图的一种更复杂的方法!根据文档,似乎
。accentColor
应该更改
切换开关的颜色。也许向苹果公司提交一份bug报告,看看他们怎么说?。它似乎是与SwiftUI中UIKit的tintColor最接近的选项,这就是为什么我说它似乎应该更改Toggle的颜色。如果你提交了一个关于它的bug报告,那么不管是谁做出响应,都应该确认它是一个bug还是存在另一个bug
Toggle("", isOn: $toggleState)
    .toggleStyle(
        ColoredToggleStyle(label: "My Colored Toggle",
                           onColor: .green,
                           offColor: .red,
                           thumbColor: Color(UIColor.systemTeal)))

Toggle("", isOn: $toggleState2)
    .toggleStyle(
        ColoredToggleStyle(label: "My Colored Toggle",
                           onColor: .purple))
@State var enable_dhcp = true

init()
{
    UISwitch.appearance().onTintColor = .red
}

var body: some View
{
    Toggle("DHCP", isOn: $enable_dhcp)
}
import SwiftUI

struct CustomToggle: UIViewRepresentable {
  @Binding var isOn: Bool

  func makeCoordinator() -> CustomToggle.Coordinator {
    Coordinator(isOn: $isOn)
  }

  func makeUIView(context: Context) -> UISwitch {
    let view = UISwitch()
    view.onTintColor = UIColor.red
    view.addTarget(context.coordinator, action: #selector(Coordinator.switchIsChanged(_:)), for: .valueChanged)

    return view
  }

  func updateUIView(_ uiView: UISwitch, context: Context) {
    uiView.isOn = isOn
  }

  class Coordinator: NSObject {
    @Binding private var isOn: Bool

    init(isOn: Binding<Bool>) {
      _isOn = isOn
    }

    @objc func switchIsChanged(_ sender: UISwitch) {
      _isOn.wrappedValue = sender.isOn
    }
  }
}

// MARK: - Previews

struct CustomToggle_Previews: PreviewProvider {
  static var previews: some View {
    ViewWrapper()
  }

  struct ViewWrapper: View {
    @State(initialValue: false) var isOn: Bool

    var body: some View {
      CustomToggle(isOn: $isOn)
        .previewLayout(.fixed(width: 100, height: 100))
    }
  }
}
UISwitch.appearance().onTintColor = .blue
appearance(whenContainedInInstancesOf:)
// Switch tinting

Toggle(isOn: $order.notifyWhenReady) {
    Text("Send notification when ready")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))