Stephanie Chiu
Stephanie Chiu

Reputation: 79

RGB slider color showing in grayscale instead of in color

I'm making a RGB slider programmatically and I've come across an issue where I can't seem to figure out how to properly show the color of each sliders' values as a UIColor. I've gotten as far as changing the colors in the box, but they come out grayscale and I don't understand why.

View class:

extension UIView {
    func colorSlider(tintColor: UIColor) -> UISlider {
        let slider = UISlider()
        slider.minimumValue = 0
        slider.maximumValue = 255
        slider.isContinuous = true
        slider.tintColor = tintColor
        slider.frame.size = CGSize(width: 250, height: 20)
        return slider
    }
}

class SliderView: UIView {

    let stackView: UIStackView
    let redColorSlider = UIView().colorSlider(tintColor: .red)
    let greenColorSlider = UIView().colorSlider(tintColor: .green)
    let blueColorSlider = UIView().colorSlider(tintColor: .blue)

    let previewColorButton: UIButton = {
        let button = UIButton()
        button.frame.size = CGSize(width: 80, height: 100)
        return button
    }()

    override init(frame: CGRect) {
        self.stackView = UIStackView(arrangedSubviews: [redColorSlider, greenColorSlider, blueColorSlider])
        stackView.distribution = .fillEqually
        stackView.spacing = 15
        stackView.axis = .vertical

        super.init(frame: frame)

        setupLayout()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    fileprivate func setupLayout() {
        backgroundColor = .white

        addSubview(previewColorButton)
        previewColorButton.anchor(left: leftAnchor, paddingLeft: 20, width: 80, height: 100)
        previewColorButton.centerY(inView: self)

        addSubview(stackView)
        stackView.anchor(left: previewColorButton.rightAnchor, paddingLeft: 20, paddingRight: 20, width: 250)
        stackView.centerY(inView: self)

    }
}


Controller class:

class SliderController: UIViewController {

    let sliderView = SliderView()
    let step: Float = 0.1
    let redLabel = UIView().rgbLabel()
    var redValue: CGFloat = 0
    let greenLabel = UIView().rgbLabel()
    var greenValue: CGFloat = 0
    let blueLabel = UIView().rgbLabel()
    var blueValue: CGFloat = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        view = sliderView

        redLabel.text = "0"
        greenLabel.text = "0"
        blueLabel.text = "0"
        sliderView.previewColorButton.backgroundColor = .blue

        sliderView.redColorSlider.addTarget(self, action: #selector(sliderValueChanged(sender:)), for: .valueChanged)
        sliderView.greenColorSlider.addTarget(self, action: #selector(sliderValueChanged(sender:)), for: .valueChanged)
        sliderView.blueColorSlider.addTarget(self, action: #selector(sliderValueChanged(sender:)), for: .valueChanged)
        sliderView.previewColorButton.addTarget(self, action: #selector(sliderValueChanged(sender:)), for: .valueChanged)

        let stackView = UIStackView(arrangedSubviews: [redLabel, greenLabel, blueLabel])
        stackView.distribution = .fillEqually
        stackView.spacing = 5

        view.addSubview(stackView)
        stackView.anchor(bottom: view.safeAreaLayoutGuide.bottomAnchor)
        stackView.centerX(inView: view)
    }

    @objc func sliderValueChanged(sender: UISlider) {
        redValue = CGFloat(round(sender.value / step) * step)
        greenValue = CGFloat(round(sender.value / step) * step)
        blueValue = CGFloat(round(sender.value / step) * step)
        redLabel.text = "\(Int(redValue))"
        greenLabel.text = "\(Int(greenValue))"
        blueLabel.text = "\(Int(blueValue))"

        sliderView.previewColorButton.backgroundColor = UIColor(red: redValue/255, green: greenValue/255, blue: blueValue/255, alpha: 1.0)
    }

I've tried separating the slider action function @objc func sliderValueChanged to each individual slider action like so:

    @objc func redSliderValueDidChange(sender: UISlider) {
        let redSliderValue = round(sender.value / step) * step
        redValue = CGFloat(redSliderValue)
        redLabel.text = "\(Int(redValue))"
    }

    @objc func greenSliderValueDidChange(sender: UISlider) {
        let greenSliderValue = round(sender.value / step) * step
        greenValue = CGFloat(greenSliderValue)
        greenLabel.text = "\(Int(greenValue))"
    }

    @objc func blueSliderValueDidChange(sender: UISlider) {
        let blueSliderValue = round(sender.value / step) * step
        blueValue = CGFloat(blueSliderValue)
        blueLabel.text = "\(Int(blueValue))"
    }

This helps so that each color label changes individually, as opposed to what I have above, but the colors don't change.

How it looks currently: enter image description here

I haven't found any information on how to do this programmatically, so any help is appreciated!

Upvotes: 0

Views: 570

Answers (1)

Ved Sharma
Ved Sharma

Reputation: 769

Please check the targets you have added to the slider.

Also, you can replace the following method in your code:

@objc func sliderValueChanged(sender: UISlider)
{
    sliderView.previewColorButton.backgroundColor = UIColor(red: CGFloat(redSliderValue/255), green: CGFloat(greenSliderValue/255), blue: CGFloat(blueSliderValue/255), alpha: 1.0)
}

Upvotes: 1

Related Questions