There’s lot of ways to represent colors. Crayons have names like Sea Green and Peach.
I used these two colors since I’m color blind and they once got me in serious trouble when I was young. I and many with color blindness can’t tell them apart easily. Knowing some other identifying system is critical in describing colors not only for the colorblind, but anyone trying to communicate colors.
As developers, we often use RGB colors. UIColor
has a initializer for RGB, using CGFloat
values between 0 and 1. One of the most common shorthands for RGB values used in web and graphic design applications is the six digit hex value.
UIKit does not include an initializer for this value. Fortunately with some bit masking you learned in a previous tip its easy to convert from a hex value to a UIColor
. Let me show you how, and a quick tip to get a matching color.
Hex colors use eight bits, or two hex digits, to represent the three primary colors in an RGB color. The rightmost two digits are blue, next to that green and to the left red. If you separate to those numbers ranging from 0 – 255 you can divide them by 255 and get the values needed for UIColor.
On Github you can find the starter file, which has an application for setting the color of two buttons. I have a text field for entry, and a go button to press that entry.
Make a new function color
func color(from hexColorNumber:UInt32) -> UIColor { }
I used a UInt32
here, so I can hold the 24 bits of the RGB value. I’ll use some of the tricks we learned in an earlier tip about bit masking. The blue is the rightmost 8 bits. I can use a bit mask to get only the blue bits.
let blue = (hexColorNumber & 0x0000ff)
The eight bits to the left of blue are green. I can do the same thing for green,
let green = (hexColorNumber & 0x00ff00)
but I also will need to shift them back eight bits
let green = (hexColorNumber & 0x00ff00) >> 8
For red, I can follow a similar pattern, shifting sixteen bits to the right.
let red = (hexColorNumber & 0xff0000) >> 16
With these integer values between 0 and 255, I can convert them to CGFloat
and divide by 255 to get a CGFloat
between 1 and 0 as UIColor
requires, returning the UIColor
.
return UIColor( red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: alpha )
This is function that takes UInt32
and converts it into a UIColor
. You might want a function that converts from String
. Add another function.
func color(from string:String) -> UIColor{}
There’s a initializer for unsigned integers that uses a string representation of a number and radix
, the base system for the number. It returns an optional value, returning nil
if it cannot translate the number correctly. You’ll need to unwrap the result to use it. I’ll do that with a UInt32
if let colorNumber = UInt32(string, radix:16){ }
I can return a color from my first color function
return color(from: colorNumber)
If nil
, I’ll return black.
return UIColor.black
Here’s little trick to get a decent matching color. Copy and paste the color(from: String)
function. Change the name of the copy to colorComplement
.
In the return, pass back NOT color number.
return color(from: ~colorNumber)
In hue, this is a complement, but the lightness and saturation of the color is also opposite.
Change the updateColor
method to use these. Set the topButton‘s background color to the color, and its tint to the color complement
topButton.backgroundColor = color(from: colorString) topButton.tintColor = colorComplement(from: colorString)
Then do the opposite with the bottom button.
bottomButton.backgroundColor = colorComplement(from: colorString, alpha: 1.0) bottomButton.tintColor = color(from: colorString)
Set your simulator to iPhone 8 plus. Build and run. At the top you can enter a color.
I set teh code to default to yellow which is FFFF00
. With that, you get yellow on top and its complement on the bottom. The sea green with is a green-blue 54ff9f
has complement of red with a little blue.
Of course, I didn’t include the alpha value here. Since you have enough space in a UInt32
, you should be able to use this same technique to add transparency on your own.
This was a text version of the iOS Development Tips Weekly video series you can find at the Lynda.com and LinkedIn Learning libraries. The first week of a week’s tip will be available for free. After that, you will need a subscription to get access to it. Click the image at left to view.
The Whole Code
This project is available for download on GitHub
// // ViewController.swift // HexColorComplement // // Created by Steven Lipton on 2/9/18. // Copyright © 2018 Steven Lipton. All rights reserved. // import UIKit class ViewController:UIViewController{ @IBOutlet weak var topButton: UIButton! @IBOutlet weak var bottomButton: UIButton! @IBOutlet weak var textField: UITextField! //MARK: - Actions @IBAction func goButton(_ sender: UIButton) { textField.resignFirstResponder() updateColor(colorString: textField.text!) } @IBAction func newColor(_ sender: UIButton) { textField.becomeFirstResponder() } func color(from hexColorNumber:UInt32) -> UIColor{ let blue = hexColorNumber & 0x0000ff let green = (hexColorNumber & 0x00ff00) >> 8 let red = (hexColorNumber & 0xff0000) >> 16 return UIColor(red: CGFloat(red) / 255.0 , green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0) } func color(from string:String) -> UIColor{ if let colorNumber = UInt32(string, radix:16){ return color(from: colorNumber) } else { return UIColor.black } } func colorComplement(from string:String) -> UIColor{ if let colorNumber = UInt32(string, radix:16){ return color(from: ~colorNumber) } else { return UIColor.black } } func updateColor(colorString:String){ topButton.backgroundColor = color(from: colorString) topButton.tintColor = colorComplement(from: colorString) bottomButton.backgroundColor = colorComplement(from: colorString) bottomButton.tintColor = color(from: colorString) } override func viewDidLoad() { super.viewDidLoad() updateColor(colorString:"ffff00") } }
Leave a Reply