在“关闭”状态下更改UISwitch的颜色


97

我了解到,我们可以在“打开”状态下更改UISwitch按钮的外观,但是也可以在“关闭”状态下更改UISwitch的颜色吗?


您是否使用过tintColor属性更改颜色?
rishi 2012年

Answers:


134

我的#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

结果:

在此处输入图片说明


6
嘿,@longpham,我只想对半径代码做些改动。如果高度发生变化,我将使用:mSwitch.layer.cornerRadius = mSwitch.frame.height / 2(我只是偏执狂)。
费利佩2015年

@Felipe Gringo没问题。取决于您的UI。标准UISwitch为31pt。
Long Pham 2015年

132

试试这个

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

感谢@Barry Wyckoff。


2
这是正确的答案:) setTint也会更改“轮廓”颜色,从而在视觉上“隐藏”白色背景上的背景。
Lukasz'Severiaan'Grela 2014年

2
请注意,背景为矩形。
Lukasz'Severiaan'Grela 2014年

我的开关使用调整了大小CGAffineTransformMakeScale(0.80, 0.80)。这不适用于缩放视图。因为视图的图层未调整大小。我该如何工作?
aykutt

1
@aykutt用于缩放视图,可以使用yourSwitch.layer.cornerRadius = yourSwitch.frame.height / 2 / scaleFactor
Hans Terje Bakke,

37

您可以tintColor在开关上使用该属性。

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

请注意,这需要iOS 5+


3
在iOS7中设置tintColor会为我删除“轮廓”(在白色背景下为白色)。
Lukasz'Severiaan'Grela 2014年

28

迅捷IBDesignable

import UIKit
@IBDesignable

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

在身份检查器中设置类

在此处输入图片说明

从属性检查器更改颜色

在此处输入图片说明

输出量

在此处输入图片说明


它并没有给予应有的重视3
Ketan P

@KetanP您可以更详细地解释问题吗?
Afzaal Ahmad

运行Xcode 11.2.1的程序可以在运行应用程序时使用,但是它不会在IB中显示颜色。
zumzum

9

这是一个很好的技巧:您可以直接进入UISwitch的子视图,该子视图绘制其“关闭”背景,并更改其背景颜色。在iOS 13中,此方法比在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

管理UISwitch背景颜色和大小的最佳方法

现在是Swift 2.3代码

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

在Swift 4+中:

off 州:

switch.tintColor = UIColor.blue

on 州:

switch.onTintColor = UIColor.red

2
这在iOS 13+上不起作用,设置tintColor无效。
埃里克

5

斯威夫特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最简单,最快的方法,分三个步骤:

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

如果您手动更改开关的大小(例如,通过使用自动布局),则也将必须更新开关的大小switch.layer.cornerRadius,例如,通过覆盖layoutSubviews并调用超级更新角半径后:

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

什么是IntegrationSwitch?而且,在iOS 11中似乎不起作用。更改背景颜色会更改开关
FlowUI

@iOSCalendarViewOnMyProfile抱歉,应该是switchControl
MilanNosáľ18年

1
@iOSCalendarViewOnMyProfile它应该改变背景颜色,而不是子弹本身..在iOS的外观和感觉,总是默认的颜色..
米兰诺萨尔

4

如果您的应用需要其他开关,在自定义类中实现@LongPham的代码也是个好主意。正如其他人指出的那样,对于“关闭”状态,您还需要更改背景颜色,因为默认设置是透明的。

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

UISwitch offTintColor是透明的,因此开关后面的内容都可以显示出来。因此,与其掩盖背景色,不如在开关后面绘制一个开关形状的图像(此实现假定开关是通过自动布局放置的):

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

[但是现在看看我的其他答案。]


2

2020年截至Xcode 11.3.1和Swift 5

这是我用一行代码设置UISwitch的关闭状态颜色的最简单方法。由于此页面是我在看时首先想到的内容,所以在这里写下来,其他答案无济于事。

这是如果我要将关闭状态设置为红色,并且可以将其添加到viewDidLoad()函数中:

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

注意-这实际上是在设置开关的背景色。这也可能会影响打开状态下开关的颜色(尽管对我来说这不是问题,因为我希望打开和关闭状态为同一颜色)。

一个解决方案:

只需在IBAction中用“ if else”语句添加颜色即可。如果开关关闭,则将背景色为红色。如果开关打开,请使背景保持清晰,以便您选择的“打开”颜色将正确显示。

开关IBAction 内部

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

我发现了一些行为,在该应用程序从后台恢复时,切换后台将恢复为清除状态。为了解决此问题,我仅添加了以下代码即可在应用程序每次进入前台时设置颜色:

 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
}

似乎比其他答案更简单。希望有帮助!


漂亮而简单的答案,非常感谢您+1
mAc

1

Swift 3中更安全的方法,没有神奇的16pt值:

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

我不喜欢使用subViews,因为您永远不知道苹果何时会更改层次结构。

所以我改用遮罩视图。

它适用于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

在此处输入图片说明
在此处输入图片说明
工作100%IOS 13.0和Swift 5.0都将两个状态颜色设置为相同#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

Matt的解决方案开始,我将其添加到自定义IBDesignable控件中。在设置需要处理的didMoveToSuperview()之前,存在一个时序问题offTintColor

@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

使用代码或情节提要在项目中的任何UISwitch上使用的目标c类别:

#import <UIKit/UIKit.h>

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

实施

#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

我最终也都使用了transform和layer.cornerRadius。但是我添加了翻译以使其成为中心。

    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
}

我确实在设计器中使用了backgroundColor和tintColor。希望能帮助到你。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.