Set random color for a cgfill in external function - swift

I have a rectangle and I want to fill it with a random color.
The function for returning the random color should be seperate.
This is my idea but it does not work out, I think because of the type? Do I need to do this with pointers?
func getRandomColor() -> CGColorRef {
let color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), [1.0, 0.5, 0.5, 0.2])
return color
}
func drawRect {
// ...
CGContextSetFillColorwithcolor(context,getRandomColor())
// ...
}

func randomColorComponent() -> CGFloat
{
return CGFloat(Float(arc4random()) / Float(UINT32_MAX))
}
func randomColorRef() -> CGColorRef
{
let red = randomColorComponent()
let green = randomColorComponent()
let blue = randomColorComponent()
return UIColor(red: red, green: green, blue: blue, alpha: 1).CGColor
}
and then somewhere in your drawRect use:
CGContextSetFillColorWithColor(context, randomColorRef())

Related

Hex codes/RGB values for SwiftUI colors?

is there a compiled list of hex codes or RGB values for SwiftUI colors? I'd like to know either for Color.purple but can't seem to find any good sources. Is there a way to programmatically determine the hex code or RGB value? Or maybe I can look at some properties of Color? Thanks in advance!
If you are coding in SwiftUI 2 you can convert your Color to UIColor and use getRed method to get the red, green, blue and alpha components. Once you have the components you can convert the values to hexa string:
extension Color {
var uiColor: UIColor { .init(self) }
typealias RGBA = (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
var rgba: RGBA? {
var (r, g, b, a): RGBA = (0, 0, 0, 0)
return uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) ? (r, g, b, a) : nil
}
var hexaRGB: String? {
guard let (red, green, blue, _) = rgba else { return nil }
return String(format: "#%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255))
}
var hexaRGBA: String? {
guard let (red, green, blue, alpha) = rgba else { return nil }
return String(format: "#%02x%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255),
Int(alpha * 255))
}
}
Color.purple.hexaRGB // "#af52de"
Color.purple.hexaRGBA // "#af52deff"
if let (red, green, blue, alpha) = Color.purple.rgba {
red // 0.686274528503418
green // 0.321568638086319
blue // 0.8705882430076599
alpha // 1
}
Isn't it good to use it like this?
import UIKit
extension UIColor {
convenience init(hex:Int, alpha: CGFloat = 1.0) {
self.init(
red: CGFloat((hex & 0xFF0000) >> 16) / 255.0,
green: CGFloat((hex & 0x00FF00) >> 8) / 255.0,
blue: CGFloat((hex & 0x0000FF) >> 0) / 255.0,
alpha: alpha
)
}
}

How to convert a UIColor to a black and white UIColor

I am setting the background color of my label, but I would like to have the color be the black and white UIColor instead of the original UIColor.
self.MyLabel.backgroundColor = self.selectedColors.color
Looks like you'll need to convert your colour to grayscale.
While you can do this by averaging the R, G and B components of the colour, apple actually provide a nice method to grab the grayscale value:
func getWhite(_ white: UnsafeMutablePointer<CGFloat>?,
alpha: UnsafeMutablePointer<CGFloat>?) -> Bool
So to use this, you would first extract the grayscale colour and then init a new UIColor:
let originalColor = self.selectedColors.color
var white: CGFloat = 0
var alpha: CGFloat = 0
guard originalColor.getWhite(&white, alpha: &alpha) else {
// The color couldn't be converted! Handle this unexpected error
return
}
let newColor = UIColor(white: white, alpha: alpha)
self.MyLabel.backgroundColor = newColor
By thanks of #Sam answer, I write an extension for UIColor:
extension UIColor {
var grayScale: UIColor? {
var white: CGFloat = 0
var alpha: CGFloat = 0
guard self.getWhite(&white, alpha: &alpha) else {
return nil
}
return UIColor(white: white, alpha: alpha)
}
}
You can use it like this:
var grayScaleColorOfRed = UIColor.red.grayScale ?? UIColor.grey

Swift Random Color Generator

Is it possible to change the color a button with a label using a random generator?
For ex.. Label "A" is the title/color dictator and will notify "Button 1 and Button 2" what colors they will generate to be randomly.
let randomRed:CGFloat = CGFloat(arc4random_uniform(256))
let randomGreen:CGFloat = CGFloat(arc4random_uniform(256))
let randomBlue:CGFloat = CGFloat(arc4random_uniform(256))
let myColor = UIColor(red: randomRed/255, green: randomGreen/255, blue: randomBlue/255, alpha: 1.0)
Try this code:
Answer 1: Generate random colour from array(restrict to 3 colour)
Note: you have to set initial backgroundColor to your button in viewDidLoad
yourButtonName.backgroundColor = .red // set any colour
//Button background array
let buttonBG = [UIColor.red,UIColor.green,UIColor.black]
//Button title colour array
let buttonTitle = [UIColor.orange,UIColor.cyan,UIColor.yellow]
Usage: Try below code inside your button action.It will generate randomColor assigned from array...
let BGRandomIndex = Int(arc4random_uniform(UInt32(buttonTitle.count)))
yourButtonName.tintColor = buttonTitle[BGRandomIndex]
let TitleRandomIndex = Int(arc4random_uniform(UInt32(buttonBG.count)))
yourButtonName.backgroundColor = buttonBG[TitleRandomIndex]
Answer 2: Generate Random Colour.
func randomCGFloat() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
func randomColor() -> UIColor {
let r = randomCGFloat()
let g = randomCGFloat()
let b = randomCGFloat()
// If you wanted a random alpha, just create another
// random number for that too.
return UIColor(red: r, green: g, blue: b, alpha: 1)
}
Usage: Try below code inside your button action.It will generate randomColor on every button click...
yourButtonName.backgroundColor = randomColor() // to get random background button backgroundColor
yourButtonName.tintColor = randomColor() //to get random background button title color
public func getRandomColor() -> UIColor{
let randomRed:CGFloat = CGFloat(drand48())
let randomGreen:CGFloat = CGFloat(drand48())
let randomBlue:CGFloat = CGFloat(drand48())
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
}
You're going to need a function to produce random CGFloats in the range 0 to 1:
you can use
CGFloat(arc4random()) / CGFloat(UInt32.max)
alternate for drand48()
If you want a alpha as a random, just create another random number for that
Just create a random background for your view like
self.view.backgroundColor = UIColor().getRandomColor()

Computing complementary, triadic, tetradic, and analagous colors

I have created swift functions, where I send color value to and want to return triadic and tetrads values. It sort of works, but I am not happy about the color results. Can anyone help me to fine-tune the formula please?
I was following few sources, but the returned colours were too bright or saturated in comparison to several online web based color schemes. I know it's a matter of preference as well and I kinda like the results of the code below, but in some instances of colors the result of one color returned is way too close to the original one, so it's barely visible. It applies only to a few colors...
I was using the formula from here:
my code:
func getTriadColor(color: UIColor) -> (UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let triadHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let triadColor1 = UIColor(hue: (triadHue + 0.33) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let triadColor2 = UIColor(hue: (triadHue + 0.66) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (triadColor1, triadColor2)
}
func getTetradColor(color: UIColor) -> (UIColor, UIColor, UIColor){
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
let tetradHue = CGFloat(color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha))
let tetradColor1 = UIColor(hue: (tetradHue + 0.25) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor2 = UIColor(hue: (tetradHue + 0.5) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
let tetradColor3 = UIColor(hue: (tetradHue + 0.75) - 1.0, saturation: saturation, brightness: brightness, alpha: alpha)
return (tetradColor1, tetradColor2, tetradColor3)
}
And I also found nice clean code for finding complementary color, which I am very happy about the results
func getComplementColor(color: UIColor) -> UIColor{
let ciColor = CIColor(color: color)
let compRed: CGFloat = 1.0 - ciColor.red
let compGreen: CGFloat = 1.0 - ciColor.green
let compBlue: CGFloat = 1.0 - ciColor.blue
return UIColor(red: compRed, green: compGreen, blue: compBlue, alpha: 1.0)
}
Your screen shot is of this web page. (Wayback Machine link because, six years later, the page has been deleted.) The formulas on that page are incorrect, because they specify the use of the absolute value function instead of the modulo function. That is, for example, your screen shot defines
H1 = |(H0 + 180°) - 360°|
but consider what this gives for the input H0 = 90°:
H1 = |(90° + 180°) - 360°| = |270° - 360°| = |-90°| = 90°
Do you think that the complementary hue of H0 = 90° is H1 = 90°, the same hue?
The correct formula is
H1 = (H0 + 180°) mod 360°
where “mod” is short for “modulo” and means “the remainder after dividing by”. In other words, if the answer would be above 360°, subtract 360°. For H0 = 90°, this gives the correct answer of H1 = 270°.
But you don't even have this problem in your code, because you didn't use the absolute value function (or the modulo function) in your code. Since you're not doing anything to keep your hue values in the range 0…1, your hue values that are less than zero are clipped to zero, and your hue values above one are clipped to one (and both zero and one mean red).
Your getComplementColor is also not at all the standard definition of the “complementary color”.
Here are the correct definitions:
extension UIColor {
var complement: UIColor {
return self.withHueOffset(0.5)
}
var splitComplement0: UIColor {
return self.withHueOffset(150 / 360)
}
var splitComplement1: UIColor {
return self.withHueOffset(210 / 360)
}
var triadic0: UIColor {
return self.withHueOffset(120 / 360)
}
var triadic1: UIColor {
return self.withHueOffset(240 / 360)
}
var tetradic0: UIColor {
return self.withHueOffset(0.25)
}
var tetradic1: UIColor {
return self.complement
}
var tetradic2: UIColor {
return self.withHueOffset(0.75)
}
var analagous0: UIColor {
return self.withHueOffset(-1 / 12)
}
var analagous1: UIColor {
return self.withHueOffset(1 / 12)
}
func withHueOffset(offset: CGFloat) -> UIColor {
var h: CGFloat = 0
var s: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
self.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return UIColor(hue: fmod(h + offset, 1), saturation: s, brightness: b, alpha: a)
}
}
Here are some examples of complementary colors (original on top, complementary beneath):
Here are split complementary colors (original on top):
Here are triadic colors (original on top):
Here are tetradic colors (original on top):
Here are analagous colors (original in the middle):
Here is the playground I used to generate those images:
import XCPlayground
import UIKit
let view = UIView(frame: CGRectMake(0, 0, 320, 480))
view.backgroundColor = [#Color(colorLiteralRed: 0.9607843137254902, green: 0.9607843137254902, blue: 0.9607843137254902, alpha: 1)#]
let vStack = UIStackView(frame: view.bounds)
vStack.autoresizingMask = [ .FlexibleWidth, .FlexibleHeight ]
view.addSubview(vStack)
vStack.axis = .Vertical
vStack.distribution = .FillEqually
vStack.alignment = .Fill
vStack.spacing = 10
typealias ColorTransform = (UIColor) -> UIColor
func tile(color color: UIColor) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = color
return view
}
func strip(transforms: [ColorTransform]) -> UIStackView {
let strip = UIStackView()
strip.translatesAutoresizingMaskIntoConstraints = false
strip.axis = .Vertical
strip.distribution = .FillEqually
strip.alignment = .Fill
strip.spacing = 0
let hStacks = (0 ..< transforms.count).map { (i: Int) -> UIStackView in
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .Horizontal
stack.distribution = .FillEqually
stack.alignment = .Fill
stack.spacing = 4
strip.addArrangedSubview(stack)
return stack
}
for h in 0 ..< 10 {
let hue = CGFloat(h) / 10
let color = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1)
for (i, transform) in transforms.enumerate() {
hStacks[i].addArrangedSubview(tile(color: transform(color)))
}
}
return strip
}
vStack.addArrangedSubview(strip([
{ $0 },
{ $0.complement }]))
vStack.addArrangedSubview(strip([
{ $0 },
{ $0.splitComplement0 },
{ $0.splitComplement1 }]))
vStack.addArrangedSubview(strip([
{ $0 },
{ $0.triadic0 },
{ $0.triadic1 }]))
vStack.addArrangedSubview(strip([
{ $0 },
{ $0.tetradic0 },
{ $0.tetradic1 },
{ $0.tetradic2 }]))
vStack.addArrangedSubview(strip([
{ $0.analagous0 },
{ $0 },
{ $0.analagous1 }]))
XCPlaygroundPage.currentPage.liveView = view

UIButton Borders Function Only Gives Back White Borders

I'm trying to create a Button Borders Function in Swift to help style my UI. However whatever RGB values I pass in/initialize the function only creates white borders.
Here is my function:
func buttonsWithBorders(button: UIButton, borderWidth: CGFloat, redcolour: CGFloat , greencolour: CGFloat, bluecolour: CGFloat, alpha: CGFloat?) {
let redcolour : CGFloat = 7.0
var greencolour : CGFloat = 3.0
var bluecolour : CGFloat = 2.0
var alpha: CGFloat = 1.0
var widthOfBorder: CGFloat = borderWidth
var theButtonWithBorders: UIButton
var buttonBorderColour : UIColor = UIColor(red: redcolour, green: greencolour, blue: bluecolour, alpha: alpha)
button.layer.borderWidth = widthOfBorder
return button.layer.borderColor = buttonBorderColour.CGColor
}
And I call it using:
buttonsWithBorders(learnHomeButton, 2.0,2.0, 5.0, 5.0, 1.0)
Also I know that passing in values and initializing them is incorrect but Xcode complaines that I am not initializing before using them otherwise
Any help would be very much appreciated, Cheers
You aren't initializing them. You're declaring entirely new variables with the same names as the parameters you're passing in. Whenever you use let or var you are introducing a brand new variable.
When a new variable is introduced with the same name as another currently in scope, this is known as variable shadowing, and what you have here is an almost textbook case.
A better, more concise implementation of your function might look like this:
func addButtonBorder(button: UIButton, width: CGFloat, red: CGFloat, blue: CGFloat, green: CGFloat, alpha: CGFloat = 1.0) {
button.layer.borderColor = UIColor(red: red, green: green, blue: blue, alpha: alpha).CGColor
button.layer.borderWidth = width
}
I used a different name because buttonsWithBorders implies that one or more buttons will be returned from this function. That does not appear to be your intent. Since you are passing one button in, you could only ever get one out, but "buttons" implies more than one.
If I were going to initialize a lot of buttons with borders, I might do something like this:
extension UIButton {
convenience init(frame: CGRect, borderColor: UIColor, borderWidth: CGFloat = 1.0) {
self.init(frame: frame)
setBorder(borderColor, borderWidth: borderWidth)
}
func setBorder(borderColor: UIColor, borderWidth: CGFloat = 1.0) {
layer.borderWidth = borderWidth
layer.borderColor = borderColor.CGColor
}
}
Then you could say UIButton(frame: frame, borderColor: borderColor, borderWidth: 2.0) to initialize a new button or button.setBorder(borderColor, borderWidth: 2.0) to set the border on an existing button.
UIColor takes a float between 0 and 1. So you want to divide your RGB Values by 255.0
Here is the code I used, that works on playground :
import Foundation
import UIKit
func buttonsWithBorders(button: UIButton, borderWidth: CGFloat,
redcolour:CGFloat, greencolour:CGFloat, bluecolour:CGFloat,
alpha:CGFloat) {
let buttonBorderColour : UIColor = UIColor(red: redcolour, green: greencolour, blue: bluecolour, alpha: alpha)
button.layer.borderWidth = borderWidth
return button.layer.borderColor = buttonBorderColour.CGColor
}
let learnHomeButton = UIButton(frame: CGRect(x: 0, y: 0, width: 50,
height: 50))
buttonsWithBorders(learnHomeButton, 2.0, 177/255.0, 177/255.0,
177/255.0, 1.0)
I edited the code so you can pass the colors to the function as parameters. Hope it helps.
The colour values need to be between 0.0 and 1.0 so you should define them as:
let redcolour : CGFloat = 7.0 / 255.0
var greencolour : CGFloat = 3.0 / 255.0
var bluecolour : CGFloat = 2.0 / 255.0