IOS Color Picker in Swift 3.0

I am working on an application that communicates with arduino to control RGB LED strips. I am trying to implement a color picker when you touch an image of the color spectrum and get the UIColor of the pixel that has been affected.

I want the user to be able to touch the color spectrum image anywhere and change the color to the color that they touch. To do this, I either need the RGB numbers or the UIColor of the pixel that they touch.

I found the following code that I tried to implement to no avail. here is the original description of the author:

β€œHere I did what is as simple as it gets. It's just a lightweight UIView that allows you to specify the size of an element if you want to block regions (elementSize> 1). It draws itself in the interface builder so you can set the size element and see the consequences. Just set one of your views in the interface builder to this class and then set yourself as a delegate. It will tell you when someone either clicks or clicks on it, and in this place. by itself, and you need nothing but this class, no image "Not required."

import UIKit

internal protocol HSBColorPickerDelegate : NSObjectProtocol {
    func HSBColorColorPickerTouched(sender:HSBColorPicker,     color:UIColor, point:CGPoint, state:UIGestureRecognizerState)
}

@IBDesignable
class HSBColorPicker : UIView {

weak internal var delegate: HSBColorPickerDelegate?
let saturationExponentTop:Float = 2.0
let saturationExponentBottom:Float = 1.3

@IBInspectable var elementSize: CGFloat = 1.0 {
    didSet {
        setNeedsDisplay()
    }
}

private func initialize() {
    self.clipsToBounds = true
    let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(_:)))
    touchGesture.minimumPressDuration = 0
    touchGesture.allowableMovement = CGFloat.max
    self.addGestureRecognizer(touchGesture)
}

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

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

override func drawRect(rect: CGRect) {
    let context = UIGraphicsGetCurrentContext()

    for y in (0 as CGFloat).stride(to: rect.height, by: elementSize) {

        var saturation = y < rect.height / 2.0 ? CGFloat(2 * y) / rect.height : 2.0 * CGFloat(rect.height - y) / rect.height
        saturation = CGFloat(powf(Float(saturation), y < rect.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
        let brightness = y < rect.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(rect.height - y) / rect.height

        for x in (0 as CGFloat).stride(to: rect.width, by: elementSize) {
            let hue = x / rect.width
            let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
            CGContextSetFillColorWithColor(context, color.CGColor)
            CGContextFillRect(context, CGRect(x:x, y:y, width:elementSize,height:elementSize))
        }
    }
}

func getColorAtPoint(point:CGPoint) -> UIColor {
    let roundedPoint = CGPoint(x:elementSize * CGFloat(Int(point.x / elementSize)),
        y:elementSize * CGFloat(Int(point.y / elementSize)))
    var saturation = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(2 * roundedPoint.y) / self.bounds.height
        : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
    saturation = CGFloat(powf(Float(saturation), roundedPoint.y < self.bounds.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
    let brightness = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
    let hue = roundedPoint.x / self.bounds.width
    return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
}

func getPointForColor(color:UIColor) -> CGPoint {
    var hue:CGFloat=0;
    var saturation:CGFloat=0;
    var brightness:CGFloat=0;
    color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil);

    var yPos:CGFloat = 0
    let halfHeight = (self.bounds.height / 2)

    if (brightness >= 0.99) {
        let percentageY = powf(Float(saturation), 1.0 / saturationExponentTop)
        yPos = CGFloat(percentageY) * halfHeight
    } else {
        //use brightness to get Y
        yPos = halfHeight + halfHeight * (1.0 - brightness)
    }

    let xPos = hue * self.bounds.width

    return CGPoint(x: xPos, y: yPos)
}

func touchedColor(gestureRecognizer: UILongPressGestureRecognizer){
    let point = gestureRecognizer.locationInView(self)
    let color = getColorAtPoint(point)

    self.delegate?.HSBColorColorPickerTouched(self, color: color, point: point, state:gestureRecognizer.state)
}
}

I am not sure how to make this code work in swift 3.0. I ported it as best as possible, but I get the following error: I'm not sure how to fix it:

enter image description here

and

enter image description here

for the first error, I seem to have solved it by changing the code to the next, but I'm not sure if this is correct.

private func initialize() {
    self.clipsToBounds = true
    let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(gestureRecognizer:)))
    touchGesture.minimumPressDuration = 0
    touchGesture.allowableMovement = CGFloat.greatestFiniteMagnitude
    self.addGestureRecognizer(touchGesture)
}

, , . (from:, to:, by:)

3.0.

import UIKit

internal protocol HSBColorPickerDelegate : NSObjectProtocol {
    func HSBColorColorPickerTouched(sender:HSBColorPicker, color:UIColor,    point:CGPoint, state:UIGestureRecognizerState)
}

@IBDesignable
class HSBColorPicker : UIView {

weak internal var delegate: HSBColorPickerDelegate?
let saturationExponentTop:Float = 2.0
let saturationExponentBottom:Float = 1.3

@IBInspectable var elementSize: CGFloat = 1.0 {
    didSet {
        setNeedsDisplay()
    }
}

private func initialize() {
    self.clipsToBounds = true
    let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(gestureRecognizer:)))
    touchGesture.minimumPressDuration = 0
    touchGesture.allowableMovement = CGFloat.greatestFiniteMagnitude
    self.addGestureRecognizer(touchGesture)
}

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

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

override func draw(_ rect: CGRect) {
    let context = UIGraphicsGetCurrentContext()

    for y in (0 as CGFloat).stride(to: rect.height, by: elementSize) {

        var saturation = y < rect.height / 2.0 ? CGFloat(2 * y) / rect.height : 2.0 * CGFloat(rect.height - y) / rect.height
        saturation = CGFloat(powf(Float(saturation), y < rect.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
        let brightness = y < rect.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(rect.height - y) / rect.height

        for x in (0 as CGFloat).stride(to: rect.width, by: elementSize) {
            let hue = x / rect.width
            let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
            context!.setFillColor(color.cgColor)
            context!.fill(CGRect(x:x, y:y, width:elementSize,height:elementSize))
        }
    }
}

func getColorAtPoint(point:CGPoint) -> UIColor {
    let roundedPoint = CGPoint(x:elementSize * CGFloat(Int(point.x / elementSize)),
        y:elementSize * CGFloat(Int(point.y / elementSize)))
    var saturation = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(2 * roundedPoint.y) / self.bounds.height
        : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
    saturation = CGFloat(powf(Float(saturation), roundedPoint.y < self.bounds.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
    let brightness = roundedPoint.y < self.bounds.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(self.bounds.height - roundedPoint.y) / self.bounds.height
    let hue = roundedPoint.x / self.bounds.width
    return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
}

func getPointForColor(color:UIColor) -> CGPoint {
    var hue:CGFloat=0;
    var saturation:CGFloat=0;
    var brightness:CGFloat=0;
    color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil);

    var yPos:CGFloat = 0
    let halfHeight = (self.bounds.height / 2)

    if (brightness >= 0.99) {
        let percentageY = powf(Float(saturation), 1.0 / saturationExponentTop)
        yPos = CGFloat(percentageY) * halfHeight
    } else {
        //use brightness to get Y
        yPos = halfHeight + halfHeight * (1.0 - brightness)
    }

    let xPos = hue * self.bounds.width

    return CGPoint(x: xPos, y: yPos)
}

func touchedColor(gestureRecognizer: UILongPressGestureRecognizer){
    let point = gestureRecognizer.location(in: self)
    let color = getColorAtPoint(point: point)

    self.delegate?.HSBColorColorPickerTouched(sender: self, color: color, point: point, state:gestureRecognizer.state)
}
}

, . , , !

+4
1

1) :

let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(HSBColorPicker.touchedColor(_:)))

_ :

func touchedColor(_ gestureRecognizer: UILongPressGestureRecognizer){ }

2) :

for y in stride(from: 0, to: rect.height, by: elementSize) {

, for-cycle Swift 3 :

for y in stride(from: 0, to: rect.height, by: elementSize) {
    var saturation = y < rect.height / 2.0 ? CGFloat(2 * y) / rect.height : 2.0 * CGFloat(rect.height - y) / rect.height
    saturation = CGFloat(powf(Float(saturation), y < rect.height / 2.0 ? saturationExponentTop : saturationExponentBottom))
    let brightness = y < rect.height / 2.0 ? CGFloat(1.0) : 2.0 * CGFloat(rect.height - y) / rect.height

    for x in stride(from: 0, to: rect.width, by: elementSize) {
        let hue = x / rect.width
        let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
        context!.setFillColor(color.cgColor)
        context!.fill(CGRect(x:x, y:y, width:elementSize,height:elementSize))
    }
}
+1

Source: https://habr.com/ru/post/1655583/


All Articles