Ändern Sie die Farbe des UIS-Schalters im Status "Aus"


97

Ich habe gelernt, dass wir das Erscheinungsbild der UISwitch-Schaltfläche im Status "Ein" ändern können. Ist es jedoch auch möglich, die Farbe des UIS-Schalters im Status "Aus" zu ändern?


Haben Sie die Eigenschaft tintColor verwendet, um die Farbe zu ändern?
Rishi

Antworten:


134

Meine Lösung mit # swift2:

let onColor  = _your_on_state_color
let offColor = _your_off_state_color

let mSwitch = UISwitch(frame: CGRectZero)
mSwitch.on = true

/*For on state*/
mSwitch.onTintColor = onColor

/*For off state*/
mSwitch.tintColor = offColor
mSwitch.layer.cornerRadius = mSwitch.frame.height / 2
mSwitch.backgroundColor = offColor

Ergebnis:

Geben Sie hier die Bildbeschreibung ein


6
Hey, @longpham, ich würde nur eine kleine Änderung am Radiuscode vornehmen. Für den Fall, dass sich die Höhe jemals ändert, würde ich Folgendes verwenden: mSwitch.layer.cornerRadius = mSwitch.frame.height / 2 (ich bin nur paranoid).
Felipe

@ Felipe Gringo Kein Problem. Hängen Sie von Ihrer Benutzeroberfläche ab. Standard UISwitchist 31pt.
Long Pham

132

Versuchen Sie dies zu verwenden

yourSwitch.backgroundColor = [UIColor whiteColor];
youSwitch.layer.cornerRadius = 16.0;

Vielen Dank an @Barry Wyckoff.


2
Dies ist die richtige Antwort :) setTint ändert auch die "Umriss" -Farbe, wodurch der Hintergrund auf weißem Hintergrund visuell "ausgeblendet" wird.
Lukasz 'Severiaan' Grela

2
Beachten Sie, dass der Hintergrund rechteckig ist.
Lukasz 'Severiaan' Grela

Mein Switch wird mit geändert CGAffineTransformMakeScale(0.80, 0.80). Und dies funktioniert nicht mit skalierter Ansicht. Weil die Größe der Ansichtsebene nicht geändert wird. Wie kann ich das zum Laufen bringen?
Aykutt

1
@aykutt für skalierte Ansicht können Sie yourSwitch.layer.cornerRadius = yourSwitch.frame.height / 2 / scaleFactor
Hans Terje Bakke

37

Sie können die tintColorEigenschaft für den Switch verwenden.

switch.tintColor = [UIColor redColor]; // the "off" color
switch.onTintColor = [UIColor greenColor]; // the "on" color

Beachten Sie, dass hierfür iOS 5+ erforderlich ist


3
Durch das Festlegen von tintColor in iOS7 wird "Umriss" für mich entfernt (Farbton weiß vor weißem Hintergrund).
Lukasz 'Severiaan' Grela

28

Swift IBDesignable

import UIKit
@IBDesignable

class UISwitchCustom: UISwitch {
    @IBInspectable var OffTint: UIColor? {
        didSet {
            self.tintColor = OffTint
            self.layer.cornerRadius = 16
            self.backgroundColor = OffTint
        }
    }
}

Klasse im Identitätsinspektor festlegen

Geben Sie hier die Bildbeschreibung ein

Ändern Sie die Farbe im Attributinspektor

Geben Sie hier die Bildbeschreibung ein

Ausgabe

Geben Sie hier die Bildbeschreibung ein


Es gibt nicht richtig ausgegeben in schnell 3
Ketan P

@ KetanP können Sie das Problem genauer erklären?
Afzaal Ahmad

Das Ausführen von Xcode 11.2.1 funktioniert beim Ausführen der App, zeigt jedoch nicht die Farbe in IB an. Trotzdem funktioniert es beim Bereitstellen auf dem Gerät.
Zumzum

9

Hier ist ein ziemlich guter Trick: Sie können direkt in die Unteransicht des UISwitch greifen, in der der Hintergrund "Aus" gezeichnet wird, und die Hintergrundfarbe ändern. Dies funktioniert in iOS 13 viel besser als in iOS 12:

if #available(iOS 13.0, *) {
    self.sw.subviews[0].subviews[0].backgroundColor = .green
} else if #available(iOS 12.0, *) {
    self.sw.subviews[0].subviews[0].subviews[0].backgroundColor = .green
}

6

Der beste Weg, um Hintergrundfarbe und -größe von UISwitch zu verwalten

Im Moment ist es Swift 2.3 Code

import Foundation
import UIKit

@IBDesignable
class UICustomSwitch : UISwitch {

    @IBInspectable var OnColor : UIColor! = UIColor.blueColor()
    @IBInspectable var OffColor : UIColor! = UIColor.grayColor()
    @IBInspectable var Scale : CGFloat! = 1.0

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setUpCustomUserInterface()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setUpCustomUserInterface()
    }


    func setUpCustomUserInterface() {

        //clip the background color
        self.layer.cornerRadius = 16
        self.layer.masksToBounds = true

        //Scale down to make it smaller in look
        self.transform = CGAffineTransformMakeScale(self.Scale, self.Scale);

        //add target to get user interation to update user-interface accordingly
        self.addTarget(self, action: #selector(UICustomSwitch.updateUI), forControlEvents: UIControlEvents.ValueChanged)

        //set onTintColor : is necessary to make it colored
        self.onTintColor = self.OnColor

        //setup to initial state
        self.updateUI()
    }

    //to track programatic update
    override func setOn(on: Bool, animated: Bool) {
        super.setOn(on, animated: true)
        updateUI()
    }

    //Update user-interface according to on/off state
    func updateUI() {
        if self.on == true {
            self.backgroundColor = self.OnColor
        }
        else {
            self.backgroundColor = self.OffColor
        }
    }
}

5

In Swift 4+:

off Zustand:

switch.tintColor = UIColor.blue

on Zustand:

switch.onTintColor = UIColor.red

2
Dies funktioniert nicht unter iOS 13+, die Einstellung tintColorhat keine Auswirkung.
Eric

5

Swift 5:

import UIKit

extension UISwitch {    

    func set(offTint color: UIColor ) {
        let minSide = min(bounds.size.height, bounds.size.width)
        layer.cornerRadius = minSide / 2
        backgroundColor = color
        tintColor = color
    }
}

4

Swift 4 einfachster und schnellster Weg, um es in 3 Schritten zu bekommen:

// background color is the color of the background of the switch
switchControl.backgroundColor = UIColor.white.withAlphaComponent(0.9)

// tint color is the color of the border when the switch is off, use
// clear if you want it the same as the background, or different otherwise
switchControl.tintColor = UIColor.clear

// and make sure that the background color will stay in border of the switch
switchControl.layer.cornerRadius = switchControl.bounds.height / 2

Wenn Sie manuell die Größe des Schalters ändern (zB durch Verwendung von automatischem Layout), werden Sie die aktualisieren müssen switch.layer.cornerRadiusauch zB durch zwingende layoutSubviewsund nach dem Aufruf von Super Aktualisierung des Eckenradius:

override func layoutSubviews() {
    super.layoutSubviews()
    switchControl.layer.cornerRadius = switchControl.bounds.height / 2
}

Was ist IntegrationSwitch? und scheint auch nicht in iOS 11 zu funktionieren. Durch Ändern der Hintergrundfarbe ändert sich eine größere Ansicht um den Schalter
FlowUI. SimpleUITesting.com

@ iOSCalendarViewOnMyProfile Entschuldigung, es sollte seinswitchControl
Milan Nosáľ

1
@iOSCalendarViewOnMyProfile Es soll die Hintergrundfarbe ändern, nicht die Kugel selbst. In iOS Look & Feel ist das immer die Standardfarbe.
Milan Nosáľ

4

Sollten Sie andere Schalter für Ihre App benötigen, ist es möglicherweise auch eine gute Idee, den Code von @ LongPham in einer benutzerdefinierten Klasse zu implementieren. Wie andere bereits betont haben, müssen Sie für den Status "Aus" auch die Hintergrundfarbe ändern, da die Standardeinstellung transparent ist.

class MySwitch: UISwitch {

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // Setting "on" state colour
    self.onTintColor        = UIColor.green

    // Setting "off" state colour
    self.tintColor          = UIColor.red
    self.layer.cornerRadius = self.frame.height / 2
    self.backgroundColor    = UIColor.red
  }
}

3

Der UIS-Schalter offTintColorist transparent, sodass alles, was sich hinter dem Schalter befindet, durchscheint. Anstatt die Hintergrundfarbe zu maskieren, reicht es daher aus, ein schalterförmiges Bild hinter dem Schalter zu zeichnen (diese Implementierung setzt voraus, dass der Schalter durch Autolayout positioniert wird):

func putColor(_ color: UIColor, behindSwitch sw: UISwitch) {
    guard sw.superview != nil else {return}
    let onswitch = UISwitch()
    onswitch.isOn = true
    let r = UIGraphicsImageRenderer(bounds:sw.bounds)
    let im = r.image { ctx in
        onswitch.layer.render(in: ctx.cgContext)
        }.withRenderingMode(.alwaysTemplate)
    let iv = UIImageView(image:im)
    iv.tintColor = color
    sw.superview!.insertSubview(iv, belowSubview: sw)
    iv.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        iv.topAnchor.constraint(equalTo: sw.topAnchor),
        iv.bottomAnchor.constraint(equalTo: sw.bottomAnchor),
        iv.leadingAnchor.constraint(equalTo: sw.leadingAnchor),
        iv.trailingAnchor.constraint(equalTo: sw.trailingAnchor),
    ])
}

[Aber siehe jetzt meine andere Antwort .]


2

2020 Ab Xcode 11.3.1 & Swift 5

Hier ist die einfachste Möglichkeit, die UISwitch-Off-State-Farbe mit einer Codezeile festzulegen . Das hier zu schreiben, da diese Seite zuerst auftauchte, als ich suchte und die anderen Antworten nicht halfen.

Dies ist, wenn ich den Aus-Status auf Rot setzen wollte und der Funktion viewDidLoad () hinzugefügt werden kann:

yourSwitchName.subviews[0].subviews[0].backgroundColor = UIColor.red

Hinweis - Damit wird tatsächlich die Hintergrundfarbe des Schalters eingestellt. Dies kann auch die Farbe des Schalters im eingeschalteten Zustand beeinflussen (obwohl dies für mich kein Problem war, da ich wollte, dass der Ein- und Ausschaltzustand dieselbe Farbe hat).

Eine Lösung dafür:

Binden Sie die Farben einfach mit einer "if else" -Anweisung in Ihre IBAction ein. Wenn der Schalter ausgeschaltet ist, färben Sie den Hintergrund rot. Wenn der Schalter eingeschaltet ist, lassen Sie den Hintergrund frei, damit die von Ihnen gewählte Ein-Farbe richtig angezeigt wird.

Dies geht in den Schalter IBAction.

  if yourSwitch.isOn == false {
           yourSwitch.subviews[0].subviews[0].backgroundColor = UIColor.red
    } else {
        yourSwitch.subviews[0].subviews[0].backgroundColor = UIColor.clear
    }

Ich habe ein Verhalten festgestellt, bei dem der Hintergrund des Schalters nach dem Fortsetzen der App aus dem Hintergrund wieder gelöscht wird. Um dieses Problem zu beheben, habe ich einfach den folgenden Code hinzugefügt, um die Farbe jedes Mal festzulegen, wenn die App in den Vordergrund tritt:

 override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    NotificationCenter.default.addObserver(
      self,
      selector: #selector(applicationWillEnterForeground(_:)),
      name: UIApplication.willEnterForegroundNotification,
      object: nil)
}

@objc func applicationWillEnterForeground(_ notification: NSNotification) {
   yourSwitch.subviews[0].subviews[0].backgroundColor = UIColor.red
   yourSwitch.subviews[0].subviews[0].backgroundColor = UIColor.red
}

Scheint einfacher als die anderen Antworten. Hoffentlich hilft das!


Schöne und einfache Antwort, vielen Dank, +1
mAc

1

Sicherer Weg in Swift 3 ohne magische 16-Punkte-Werte:

class ColoredBackgroundSwitch: UISwitch {

  var offTintColor: UIColor {
    get {
      return backgroundColor ?? UIColor.clear
    }
    set {
      backgroundColor = newValue
    }
  }

  override func layoutSubviews() {
    super.layoutSubviews()
    let minSide = min(frame.size.height, frame.size.width)
    layer.cornerRadius = ceil(minSide / 2)
  }

}

1

XCode 11, Swift 5

Ich bevorzuge nicht die Verwendung von SubViews, da Sie nie wissen, wann Apple die Hierarchie ändern wird.

Also benutze ich stattdessen die Maskenansicht.

es funktioniert mit iOS 12, iOS 13

    private lazy var settingSwitch: UISwitch = {
        let swt: UISwitch = UISwitch()
        // set border color when isOn is false
        swt.tintColor = .cloudyBlueTwo
        // set border color when isOn is true
        swt.onTintColor = .greenishTeal

        // set background color when isOn is false
        swt.backgroundColor = .cloudyBlueTwo

        // create a mask view to clip background over the size you expected.
        let maskView = UIView(frame: swt.frame)
        maskView.backgroundColor = .red
        maskView.layer.cornerRadius = swt.frame.height / 2
        maskView.clipsToBounds = true
        swt.mask = maskView

        // set the scale to your expectation, here is around height: 34, width: 21.
        let scale: CGFloat = 2 / 3
        swt.transform = CGAffineTransform(scaleX: scale, y: scale)
        swt.addTarget(self, action: #selector(switchOnChange(_:)), for: .valueChanged)
        return swt
    }()

    @objc
    func switchOnChange(_ sender: UISwitch) {
        if sender.isOn {
            // set background color when isOn is true
            sender.backgroundColor = .greenishTeal
        } else {
            // set background color when isOn is false
            sender.backgroundColor = .cloudyBlueTwo
        }
    }

1

Geben Sie hier die Bildbeschreibung ein
Geben Sie hier die Bildbeschreibung ein
Arbeiten 100% IOS 13.0 und Swift 5.0 schalten beide Zustandsfarben gleich # ios13 #swift # swift5

@IBOutlet weak var switchProfile: UISwitch!{
    didSet{
        switchProfile.onTintColor = .red
        switchProfile.tintColor = .red
        switchProfile.subviews[0].subviews[0].backgroundColor = .red
    }
}

0

XCode 11, Swift 4.2

Beginnend mit Matts Lösung habe ich sie einem benutzerdefinierten, IBDesignable-Steuerelement hinzugefügt. Es gibt ein Timing-Problem, didMoveToSuperview()das aufgerufen wird, bevor das offTintColorSet festgelegt wird, das behandelt werden muss.

@IBDesignable public class UISwitchCustom: UISwitch {

    var switchMask: UIImageView?
    private var observers = [NSKeyValueObservation]()

    @IBInspectable dynamic var offTintColor : UIColor! = UIColor.gray {
        didSet {
             switchMask?.tintColor = offTintColor
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        initializeObservers()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initializeObservers()
    }

    private func initializeObservers() {
        observers.append(observe(\.isHidden, options: [.initial]) {(model, change) in
            self.switchMask?.isHidden = self.isHidden
        })
    }

    override public func didMoveToSuperview() {
        addOffColorMask(offTintColor)
        super.didMoveToSuperview()
    }

   private func addOffColorMask(_ color: UIColor) {
        guard self.superview != nil else {return}
        let onswitch = UISwitch()
        onswitch.isOn = true
        let r = UIGraphicsImageRenderer(bounds:self.bounds)
        let im = r.image { ctx in
            onswitch.layer.render(in: ctx.cgContext)
            }.withRenderingMode(.alwaysTemplate)
        let iv = UIImageView(image:im)
        iv.tintColor = color
        self.superview!.insertSubview(iv, belowSubview: self)
        iv.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            iv.topAnchor.constraint(equalTo: self.topAnchor),
            iv.bottomAnchor.constraint(equalTo: self.bottomAnchor),
            iv.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            iv.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            ])
        switchMask = iv
        switchMask?.isHidden = self.isHidden
    }

}

0

Zielkategorie c, die auf jedem UISwitch im Projekt mithilfe von Code oder Storyboard verwendet werden kann:

#import <UIKit/UIKit.h>

@interface UISwitch (SAHelper)
@property (nonatomic) IBInspectable UIColor *offTint;
@end

Implementierung

#import "UISwitch+SAHelper.h"

@implementation UISwitch (SAHelper)
@dynamic offTint;
- (void)setOffTint:(UIColor *)offTint {
    self.tintColor = offTint;   //comment this line to hide border in off state
    self.layer.cornerRadius = 16;
    self.backgroundColor = offTint;
}
@end

0

Alles, was ich endlich auch mit transform und layer.cornerRadius verwendet habe. Aber ich habe die Übersetzung hinzugefügt, um im Mittelpunkt zu stehen.

    private func setSwitchSize() {
    let iosSwitchSize = switchBlockAction.bounds.size
    let requiredSwitchSize = ...
    let transform = CGAffineTransform(a: requiredSwitchSize.width / iosSwitchSize.width, b: 0,
                                      c: 0, d:  requiredSwitchSize.height / iosSwitchSize.height,
                                      tx: (requiredSwitchSize.width - iosSwitchSize.width) / 2.0,
                                      ty: (requiredSwitchSize.height - iosSwitchSize.height) / 2.0)

    switchBlockAction.layer.cornerRadius = iosSwitchSize.height / 2.0
    switchBlockAction.transform = transform
}

Und ich habe backgroundColor und tintColor in Designer verwendet. Ich hoffe es hilft.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.