在SwiftUI中设置切换颜色

时间:2019-06-06 14:27:38

标签: swift toggle swiftui

在遵循Apple的tutorial on user input之后,我实现了一个切换。当前,它看起来像这样:

这是产生此UI的代码:

NavigationView {
    List {
        Toggle(isOn: $showFavoritesOnly) {
            Text("Show Favorites only")
        }
    }
}

现在,我希望Toggle颜色上是蓝色,而不是绿色。
我尝试过:

Toggle(isOn: $showFavoritesOnly) {
    Text("Show Favorites only")
}
.accentColor(.blue)
.foregroundColor(.blue)
.background(Color.blue)

这些都不起作用,我找不到其他修饰符,例如tintColor

如何更改Toggle的颜色?

10 个答案:

答案 0 :(得分:6)

SwiftUI 2.0(WWDC-2020后)

使用新的SwiftUI增强功能,您可以使用127.0.0.1:6379> config set requirepass mypass OK 127.0.0.1:6379> auth mypass OK 127.0.0.1:6379> set EPOCH_vgsOwnedVehs_a a OK 127.0.0.1:6379> set EPOCH_vgsOwnedVehs_b a OK 127.0.0.1:6379> set EPOCH_vgsOwnedVehs_c a OK 127.0.0.1:6379> set EPOCH_vgsOwnedVehs_d a OK 127.0.0.1:6379> redis-cli -h 127.0.0.1 -p 6379 -a mypass --scan --pattern EPOCH_vgsOwnedVehs_* | xargs redis-cli -h 127.0.0.1 -p 6379 -a mypass unlink Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. (integer) 4 127.0.0.1:6379> auth mypass OK 127.0.0.1:6379> exists EPOCH_vgsOwnedVehs_a (integer) 0 修饰符。

.toggleStyle

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

答案 1 :(得分:4)

只需使用UIAppearance API:

UISwitch.appearance().onTintColor = UIColor.blue

默认情况下,根据UISwitch文档,它将默认更改UIAppearance所有实例的外观。

注意:自Xcode 11 beta 5起经过测试。

答案 2 :(得分:4)

SwiftUI 1.0

使用ToggleStyle

我创建了一个新的ToggleStyle来更改Toggle的三种颜色(颜色,关闭颜色和拇指)。

struct ColoredToggleStyle: ToggleStyle {
    var label = ""
    var onColor = Color(UIColor.green)
    var offColor = Color(UIColor.systemGray5)
    var thumbColor = Color.white

    func makeBody(configuration: Self.Configuration) -> some View {
        HStack {
            Text(label)
            Spacer()
            Button(action: { configuration.isOn.toggle() } )
            {
                RoundedRectangle(cornerRadius: 16, style: .circular)
                    .fill(configuration.isOn ? onColor : offColor)
                    .frame(width: 50, height: 29)
                    .overlay(
                        Circle()
                            .fill(thumbColor)
                            .shadow(radius: 1, x: 0, y: 1)
                            .padding(1.5)
                            .offset(x: configuration.isOn ? 10 : -10))
                    .animation(Animation.easeInOut(duration: 0.1))
            }
        }
        .font(.title)
        .padding(.horizontal)
    }
}

使用示例

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

从SwiftUI书中

Toggle Example

答案 3 :(得分:3)

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

Toggle

结果:

enter image description here

答案 4 :(得分:3)

Karol Kulesza和George Valkov提供了非常容易实现的解决方案。我只是想补充一下,您也可以将代码放在应用程序委托的didFinishLaunching方法内。

UISwitch.appearance().onTintColor = .blue

您还可以使用以下方式创建更具体的外观配置

appearance(whenContainedInInstancesOf:)

请参见https://www.hackingwithswift.com/example-code/uikit/what-is-the-uiappearance-proxy

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

https://stackoverflow.com/a/56480720/5941807(目前为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

除自定义颜色外:https://stackoverflow.com/a/57744208/5941807

答案 7 :(得分:0)

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

color = iter(cm.rainbow(np.linspace(0, 1, len(files))))

for file in files:
    d = next(color) #set the color for each file instead of inside the loop
    mesh.append(meshio.read(file))

    x = [m.points[:, 0] for m in mesh]
    y = [m.points[:, 1] for m in mesh]
    z = [m.points[:, 2] for m in mesh]

    for a,b,c in zip(x,y,z):
        plt.scatter(a,b,c,color=d)

Toggle demo UIColor(red: 226.3/255.0, green: 37.6/255.0, blue: 40.7/255.0, alpha: 1.0)

答案 8 :(得分:0)

以@ mohammad-reza-farahani的解决方案为基础,这是一种在使用SwiftUI的情况下使用实现协议获得UISwitch的可配置性的完全毫不妥协的方法。

首先将UISwitch包裹在UIViewRepresentable中,然后根据需要设置颜色:

final class CustomToggleWrapper: UIViewRepresentable {
    var isOn: Binding<Bool>

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

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

    func updateUIView(_ uiView: UISwitch, context: Context) {
        // On color
        uiView.onTintColor = UIColor.blue
        // Off color
        uiView.tintColor = UIColor.red
        uiView.layer.cornerRadius = uiView.frame.height / 2
        uiView.backgroundColor = UIColor.red
        uiView.isOn = isOn.wrappedValue

        // Update bound boolean
        uiView.addTarget(self, action: #selector(switchIsChanged(_:)), for: .valueChanged)
    }

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

第二,使用包装的UISwitch创建一个custom toggle style

struct CustomToggleStyle: ToggleStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        let toggle = CustomToggleWrapper(isOn: configuration.$isOn)

        return HStack {
            configuration.label
            Spacer()
            toggle
        }
    }
}

像往常一样实施Toggle,然后应用CustomToggleStyle

struct TestView: View {
    @State private var isOn: Bool = true

    var body: some View {
        Toggle(
            isOn: $isOn
        ) {
            Text("Test: \(String(isOn))")
        }.toggleStyle(CustomToggleStyle()).padding()
    }
}

答案 9 :(得分:0)

我会稍微改变@Mark Moeykens 的回答,以避免出现按钮点击动画。更好的解决方案是:

@available(iOS 13.0, *)
struct ColoredToggleStyle: ToggleStyle {
    var label = ""
    var onColor = UIColor.proacPrimaryBlue.suColor
    var offColor = UIColor.systemGray5.suColor
    var thumbColor = Color.white

    func makeBody(configuration: Self.Configuration) -> some View {
        HStack {
            Text(label)
            Spacer()
            RoundedRectangle(cornerRadius: 16, style: .circular)
                .fill(configuration.isOn ? onColor : offColor)
                .frame(width: 50, height: 29)
                .overlay(
                    Circle()
                        .fill(thumbColor)
                        .shadow(radius: 1, x: 0, y: 1)
                        .padding(1.5)
                        .offset(x: configuration.isOn ? 10 : -10))
                .animation(Animation.easeInOut(duration: 0.1))
                .onTapGesture {
                    configuration.isOn.toggle()
                }
        }
        .font(.title)
        .padding(.horizontal)
    }
}