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
Ich ging voran und schrieb eine einfache Farbauswahl Popover in Swift. Hoffentlich hilft es jemand anderem.
https://github.com/EthanStrider/ColorPickerExample
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.
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.
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)
}
}
}
Einfach, effektiv. Kann in jedem View-Controller platziert werden. Ich liebe es. Danke –
Unwirklich cool. TY! –
Ich mag, dass Sie den Code direkt hier in Stack Overflow platziert haben, anstatt auf ein Github-Projekt zu verlinken. – Suragch
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)
}
}
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)
}
}
Ich weiß nicht, wo in dieser Antwort ist die Antwort. – khunshan