2014-11-29 20 views
16

Gibt es eine einfache Möglichkeit, eine Farbauswahl Popover in Swift zu implementieren? Gibt es eingebaute Bibliotheken oder UI-Elemente, die ich für diesen Zweck nutzen könnte? Ich sah ein paar Farbwähler, die in Ziel-c geschrieben waren, aber sie waren mehrere Jahre alt und ich fragte mich, ob es etwas jüngeres gab.Einfache schnelle Farbauswahl Popover (iOS)

Antwort

7

Danke für den Ausgangspunkt.

Ich nahm es von dort und schrieb einen komplizierten Color PickerViewController mit einer benutzerdefinierten UIView und etwas Zeichencode.

Ich habe das benutzerdefinierte UIView @IBDesignable erstellt, damit es in InterfaceBuilder gerendert werden kann.

https://github.com/Christian1313/iOS_Swift_ColorPicker

42

Hier ist ein ich gemacht, die so einfach ist, wie es geht. Es ist nur eine einfache UIView, mit der Sie die Elementgröße angeben können, wenn Sie blockierte Bereiche (elementSize> 1) möchten. Es zeichnet sich selbst im Interface Builder auf, so dass Sie die Elementgröße festlegen und die Konsequenzen sehen können. Setzen Sie einfach eine Ihrer Ansichten im Interface Builder auf diese Klasse und legen Sie sich dann selbst als Delegat fest. Es wird Ihnen sagen, wenn jemand an dieser Stelle auf die uicolor tippt oder schleppt. Es wird sich selbst in seine eigenen Grenzen zurückziehen und es braucht nichts anderes als diese Klasse, kein Bild wird benötigt.

Element size = 1 (Standard) element size=1

Element size = 10
element size=10

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){ 
     if (gestureRecognizer.state == UIGestureRecognizerState.Began) { 
      let point = gestureRecognizer.locationInView(self) 
      let color = getColorAtPoint(point) 

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

    } 
} 
+0

Einfach, effektiv. Kann in jedem View-Controller platziert werden. Ich liebe es. Danke –

+0

Unwirklich cool. TY! –

+6

Ich mag, dass Sie den Code direkt hier in Stack Overflow platziert haben, anstatt auf ein Github-Projekt zu verlinken. – Suragch

10

Swift 3.0-Version von @joel-teply ‚s Antwort:

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(self.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 stride(from: (0 as CGFloat), 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 as CGFloat), 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) 
    } 
} 
3

Basierend auf Joel Teply Code (Swift 4), mit grauen Balken oben:

import UIKit 

protocol ColorPickerDelegate: class{ 
    func colorDidChange(color: UIColor) 
} 


class ColorPickerView : UIView { 

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

let grayPaletteHeightFactor: CGFloat = 0.1 
var rect_grayPalette = CGRect.zero 
var rect_mainPalette = CGRect.zero 

// adjustable 
var elementSize: CGFloat = 1.0 { 
    didSet { 
     setNeedsDisplay() 
    } 
} 

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

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

private func setup() { 

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



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

    rect_grayPalette = CGRect(x: 0, y: 0, width: rect.width, height: rect.height * grayPaletteHeightFactor) 
    rect_mainPalette = CGRect(x: 0, y: rect_grayPalette.maxY, 
           width: rect.width, height: rect.height - rect_grayPalette.height) 

    // gray palette 
    for y in stride(from: CGFloat(0), to: rect_grayPalette.height, by: elementSize) { 

     for x in stride(from: (0 as CGFloat), to: rect_grayPalette.width, by: elementSize) { 
      let hue = x/rect_grayPalette.width 

      let color = UIColor(white: hue, alpha: 1.0) 

      context!.setFillColor(color.cgColor) 
      context!.fill(CGRect(x:x, y:y, width:elementSize, height:elementSize)) 
     } 
    } 

    // main palette 
    for y in stride(from: CGFloat(0), to: rect_mainPalette.height, by: elementSize) { 

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

     for x in stride(from: (0 as CGFloat), to: rect_mainPalette.width, by: elementSize) { 
      let hue = x/rect_mainPalette.width 

      let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0) 

      context!.setFillColor(color.cgColor) 
      context!.fill(CGRect(x:x, y: y + rect_mainPalette.origin.y, 
           width: elementSize, height: elementSize)) 
     } 
    } 
} 



func getColorAtPoint(point: CGPoint) -> UIColor 
{ 
    var roundedPoint = CGPoint(x:elementSize * CGFloat(Int(point.x/elementSize)), 
           y:elementSize * CGFloat(Int(point.y/elementSize))) 

    let hue = roundedPoint.x/self.bounds.width 


    // main palette 
    if rect_mainPalette.contains(point) 
    { 
     // offset point, because rect_mainPalette.origin.y is not 0 
     roundedPoint.y -= rect_mainPalette.origin.y 

     var saturation = roundedPoint.y < rect_mainPalette.height/2.0 ? CGFloat(2 * roundedPoint.y)/rect_mainPalette.height 
      : 2.0 * CGFloat(rect_mainPalette.height - roundedPoint.y)/rect_mainPalette.height 

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

     return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0) 
    } 
    // gray palette 
    else{ 

     return UIColor(white: hue, 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) 
} 
*/ 

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

    self.delegate?.colorDidChange(color: color) 
} 
} 
Verwandte Themen