Swift 3.0中的IOS颜色选择器

时间:2016-09-23 08:20:19

标签: swift xcode swift3 color-picker

我正在开发一款与arduino通信的应用程序来控制RGB LED灯条。我正在尝试实现一个颜色选择器,您可以触摸颜色光谱的图像并获得被触摸的像素的UIColor。

我希望用户能够触摸色谱图像上的任何位置,并将颜色更改为他们所触摸的颜色。要做到这一点,我要么需要RGB数字或他们正在触摸的像素的UIColor。

我发现以下代码我试图实现无济于事。这是原作者描述:

“这是我制作的一个非常简单的东西。它只是一个轻量级的UIView,允许你指定元素大小,以防你想要阻塞区域(elementSize> 1)。它在界面构建器中绘制自己,所以你可以设置元素大小并查看结果。只需将界面构建器中的一个视图设置为此类,然后将自己设置为委托。它会告诉您何时有人点击或拖动它并在该位置使用uicolor。将自己绘制到自己的边界,除了这个类之外不需要任何其他东西,不需要图像。“

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

我不确定如何让这段代码在swift 3.0中运行。我尽可能地移植它但是我得到以下错误,我不确定如何解决:

enter image description here

enter image description here

对于第一个错误我似乎通过将代码更改为以下来解决了它但我不确定这是否正确

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

至于第二个错误,我不知道如何切换到使用步幅。(从:,到:,by:)

这是我尝试将其移植到swift 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)
}
}

我非常感谢你们所提供的任何帮助。如果您有更好的方法来实现我的用户可以触摸的颜色选择器的最初目标,我也会接受完全不同的建议!

1 个答案:

答案 0 :(得分:2)

<强> 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) {

因此,在Swift 3版本中添加其他修补程序的完整for-cycle应如下所示:

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