web-dev-qa-db-fra.com

Définir la couleur de basculement dans SwiftUI

J'ai implémenté une bascule après avoir suivi Apple tutoriel sur la saisie utilisateur . Actuellement, cela ressemble à ceci:

Voici le code qui produit cette interface utilisateur:

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

Maintenant, j'aimerais que le Toggle sur - la couleur soit bleue au lieu de verte.
J'ai essayé:

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

Rien de tout cela n'a fonctionné et je n'ai pas pu trouver d'autres modificateurs, tels que tintColor.

Comment changer la couleur d'un Toggle?

15
LinusGeffarth

SwiftUI 1.0

Utilisation de ToggleStyle

J'ai créé un nouveau ToggleStyle pour changer les trois couleurs du Toggle (on color, off color et the thumb).

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

Exemples d'utilisation

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

Du livre SwiftUI

Toggle Example

10
Mark Moeykens

Utilisez simplement les API UIAppearance:

UISwitch.appearance().onTintColor = UIColor.blue

Il va bien sûr par défaut changer l'apparence de toutes les instances de UISwitch, selon la documentation de UIAppearance.

REMARQUE: testé à partir de Xcode 11 beta 5.

9
Karol Kulesza

Je n'ai pas encore trouvé de moyen de changer directement une couleur Toggle mais une autre façon d'avoir un interrupteur bleu ou toute autre vue personnalisée, est de créer une vue personnalisée de votre choix. Pour créer une bascule bleue personnalisée dans sa forme la plus simple:

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

Résultat:

enter image description here

Vous pouvez modifier le onTintColor global pour tous les objets UISwitch dans init ().

@State var enable_dhcp = true

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

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

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

2
George Valkov

En s'appuyant sur la solution de @ mohammad-reza-farahani, voici une approche sans compromis pour obtenir la configurabilité d'UISwitch avec les protocoles d'implémentation de SwiftUI.

Enveloppez d'abord un UISwitch dans un UIViewRepresentable et définissez les couleurs comme vous le souhaitez:

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

Deuxièmement, créez un style de bascule personnalisé en utilisant le UISwitch enveloppé:

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

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

Implémentez un Toggle comme vous le feriez normalement et appliquez votre CustomToggleStyle:

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

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

Karol Kulesza et George Valkov ont fourni une solution très facile à mettre en œuvre. Je voulais juste ajouter que vous pouvez également placer le code ci-dessous dans la méthode didFinishLaunching du délégué de l'application.

UISwitch.appearance().onTintColor = .blue

Vous pouvez également créer des configurations d'apparence plus spécifiques avec

appearance(whenContainedInInstancesOf:)

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

1
user8468370

Cette https://stackoverflow.com/a/56480720/5941807 (pour l'instant avec Xcode 11 beta 6) est une solution. Pour basculer entre les options d'une manière rapide, utilisez le booléen au lieu de if/else:

showFavoritesOnly ? .red : .blue

pour le premier plan:

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

pour teinte:

uiView.onTintColor = showFavoritesOnly ? UIColor.blue : UIColor.gray

En plus pour les couleurs personnalisées: https://stackoverflow.com/a/57744208/5941807

0
Joannes

Comme la question d'origine était juste de changer la bascule sur la couleur et non la personnalisation visuelle complète de Toggle, je pense que quelque chose comme ça ferait:

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