Raymond
Raymond

Reputation: 1258

Can't change border colour of switch inside tableview's cell

I've a switch inside table which I'm creating programmatically. I can't change switch's off border colour to gray. I tried tint colour which isn't working either.

How to fix it?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as? TableViewCell else {
        fatalError("...")
    }
    
    //...        
    let switchView = UISwitch()
    switchView.layer.borderColor = UIColor.greyColour.cgColor
            
    cell.accessoryView = switchView
    
    return cell
}

Upvotes: -1

Views: 573

Answers (2)

Duncan C
Duncan C

Reputation: 131481

If you add a switch with code, it looks just like a switch you add in a storyboard. Neither way of creating a switch has a border color.

The code below adds a switch to a view controller's content view:

    @IBOutlet var switchView: UISwitch!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        switchView = UISwitch()
        
        switchView.translatesAutoresizingMaskIntoConstraints = false //Remember to do this for UIViews you create in code
        if false {
            //Add a gray border to the switch
            switchView.layer.borderWidth = 1.0  // Draw a rounded rect around the switchView so you can see it
            switchView.layer.borderColor = UIColor.gray.cgColor
            switchView.layer.cornerRadius = 16
        }


        //Add it to the container view
        view.addSubview(switchView)

        //Create center x & y layout anchors (with no offset to start)
        let switchViewXAnchor = switchView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0)
        switchViewXAnchor.isActive = true
        
        let switchViewYAnchor =  switchView.centerYAnchor.constraint(equalTo: view.centerYAnchor,
                                                             constant: 0.0)
        switchViewYAnchor.isActive = true
    }

It looks perfectly normal.

Upvotes: 0

ScorpiCon
ScorpiCon

Reputation: 534

You didn't specify what effect you want to achieve but for layer.borderColor to work you need to setup layer.borderWidth also. However, because switch layer is rectangular it will look like this:

enter image description here

Which might be not what you want. So to make the border follow the switcher's shape you'll need to modify its corner radius:

switchView.layer.borderColor = UIColor.gray.cgColor
switchView.layer.borderWidth = 1.0
switchView.layer.cornerRadius = 16.0

to make it looks like this:

enter image description here


Update

If you want to apply border only for switcher off state it'll be a bit more tricky because you need to handle switcher states changes. The easiest way I could think of is to subclass UISwitch and provide your own behaviour by overriding sendActions method:

class BorderedSwitch: UISwitch {
    var borderColor: UIColor = UIColor.gray {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
     }

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

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

    override var isOn: Bool {
        didSet {
            updateState()
        }
    }

    override func sendActions(for controlEvents: UIControl.Event) {
        super.sendActions(for: controlEvents)
        if controlEvents.contains(.valueChanged) {
            updateState()
        }
    }

    private func setup() {
        layer.borderColor = borderColor.cgColor
        layer.cornerRadius = frame.height / 2
        layer.borderWidth = 1.0
    }

    private func updateState() {
        layer.borderWidth = isOn ? 0.0 : 1.0
    }
}

Notice that I also updated cornerRadius value to frame.height / 2 to avoid magic numbers

Upvotes: 2

Related Questions