Why is the background color of my UIButton not affected in state config? - uibutton

I am trying to configure UIButton disabled state using attribute inspector 'state config.' How can I configure the background color for the disabled state?

Try this:
#IBAction func buttonStateChanged(sender: UIButton) {
if(sender.selected){
sender.backgroundColor = UIColor(red: 1.0, green: 0.0, blue: 0.2, alpha: 1.0)
}else{
sender.backgroundColor = UIColor(red: 1.0, green: 0.0, blue: 0.2, alpha: 1.0)
}
}

Related

tvOS - Change the width of UICollectionViewCell when focused

I have a requirement in tvOS to change the width of UICollectionViewCell when focused (width = 250) and when it unfocused, then reduce the width to normal (width = 150)
There is one solution that doesn’t look perfect, but can solve your problem:
class SomeCollectionViewCell: UICollectionViewCell {
...
private let normalCellWidth: CGFloat = 150
private let focusedCellWidth: CGFloat = 250
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocus(in: context, with: coordinator)
let scaleXValue: CGFloat = focusedCellWidth/normalCellWidth
let scaleFactor = self.isFocused ? CGAffineTransform(scaleX: scaleXValue, y: 1.0): CGAffineTransform(scaleX: 1.0, y: 1.0)
self.transform = scaleFactor
}
...
}

Adding gradient layer is causing images not to show in Xcode

Very new to this so forgive me if this is too easy. I created a gradient background for my VC and since then none of my Images on my storyboard are showing when I run the app. I attached my code and feel free to correct me.
class whoVC: UIViewController {
func setGradientBackground() {
let colorTop = UIColor(red: 119.0/255.0, green: 56.0/255.0, blue: 109.0/255.0, alpha: 2.0).cgColor
let colorBottom = UIColor(red: 185.0/255.0, green: 89.0/255.0, blue: 127.0/255.0, alpha: 2.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [ colorTop, colorBottom]
gradientLayer.locations = [ 0.0, 1.0]
gradientLayer.frame = self.view.bounds
self.view.layer.addSublayer(gradientLayer)
}
override func viewDidLoad() {
super.viewDidLoad()
setGradientBackground()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
You are saying:
self.view.layer.addSublayer(gradientLayer)
That means to put a sublayer in front of all other existing sublayers. But your subviews are sublayers. Therefore the gradient covers all your subviews. If that's not what you want, don't do that.
To put the layer to the background, you should use insertSubLayer instead of addSubLayer
view.layer.insertSublayer(yourLayer, atIndex: yourIndex)
The index of the layer should be 0

Convert NSColor to RGB

I'm trying to convert an NSColor to RGB, but it seems to give an entirely incorrect result:
NSColor *testColor = [NSColor colorWithCalibratedWhite:0.65 alpha:1.0];
const CGFloat* components = CGColorGetComponents(testColor.CGColor);
NSLog(#"Red: %f", components[0]);
NSLog(#"Green: %f", components[1]);
NSLog(#"Blue: %f", components[2]);
NSLog(#"Alpha: %f", CGColorGetAlpha(testColor.CGColor));
I get back : red = 0.65 - green = 1.0 - blue = 0.0 and alpha is 1.0 - which results in an entirely different color. (It should be gray, now it's green).
Am I doing something wrong?
Extracting RGBA values from NSColor: (Swift 3)
let nsColor: NSColor = .red
let ciColor: CIColor = .init(color: nsColor)!
print(ciColor.red) // 1.0
print(ciColor.green) // 0.0
print(ciColor.blue) // 0.0
print(ciColor.alpha) // 1.0 // Or use nsColor.alphaComponent
NOTE: NSColor.blackColor().redComponent will crash the app, but the above code won't
I had the same problem when I wanted to convert a picked color to hexadecimal. NSColor components values was not correct. I managed to resolve my problem with your comment above.
Example in Swift:
let colorTest = NSColor.init(calibratedWhite: 0.65, alpha: 1.0)
let color = colorTest.usingColorSpace(NSColorSpace.deviceRGB) ?? colorTest
print(colorTest)
// NSCalibratedWhiteColorSpace 0.65 1
print(colorTest.colorSpace)
// Generic Gray colorspace
print("red: \(color.redComponent) green:\(color.greenComponent) blue:\(color.blueComponent)")
// red: 0.708725869655609 green:0.708725869655609 blue:0.708725869655609
You need to convert the color to an RGB color space using an NSColorSpace object first, then you can get the components using the various NSColor accessor methods
For a NSColor * color
CGFloat red = [color redComponent];
CGFloat green = [color greenComponent];
CGFloat blue = [color blueComponent];
I have used this in the past, and it worked for me.
NSColorSpace *colorSpace = [NSColorSpace sRGBColorSpace];
NSColor *testColor = [NSColor colorWithColorSpace:colorSpace components:SRGB];
CGFloat red = [testColor redComponent];
CGFloat green = [testColor greenComponent];
CGFloat blue = [testColor blueComponent];
You have to check the colorspace first
then if it's rgb you can use
CGFloat red = [testColor redComponent];
...
For grayscale you have to convert it differently
CGFloat red = [testColor whiteComponent];
CGFloat blue = [testColor whiteComponent];
CGFloat green = [testColor whiteComponent];
Here’s a safe Swift 5 SKColor extension for getting the RGB components of an NSColor or UIColor. (Note SKColor is just a typealias for one or the other based on the platform.)
public extension SKColor {
var sRGBAComponents: (red: CGFloat , green: CGFloat, blue: CGFloat, alpha: CGFloat) {
#if os(iOS)
let rgbColor = self // lolz no color conversion on iOS, but on iOS it'll respond to getRed(...) anyhow
#elseif os(macOS)
let rgbColor = usingColorSpace(.extendedSRGB) ?? SKColor(red: 1, green: 1, blue: 1, alpha: 1) // will return 'self' if already RGB
#endif
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
rgbColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red: red, green: green, blue: blue, alpha: alpha)
}
}

Get Slightly Lighter and Darker Color from UIColor

I was looking to be able to turn any UIColor into a gradient. The way I am intending to do this is by using Core Graphics to draw a gradient. What I am trying to do is to get a color, lets say:
[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
and get a UIColor which is a few shades darker and a few shades lighter. Does anyone know how to do this? Thank you.
- (UIColor *)lighterColorForColor:(UIColor *)c
{
CGFloat r, g, b, a;
if ([c getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MIN(r + 0.2, 1.0)
green:MIN(g + 0.2, 1.0)
blue:MIN(b + 0.2, 1.0)
alpha:a];
return nil;
}
- (UIColor *)darkerColorForColor:(UIColor *)c
{
CGFloat r, g, b, a;
if ([c getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MAX(r - 0.2, 0.0)
green:MAX(g - 0.2, 0.0)
blue:MAX(b - 0.2, 0.0)
alpha:a];
return nil;
}
Use it like this:
UIColor *baseColor = // however you obtain your color
UIColor *lighterColor = [self lighterColorForColor:baseColor];
UIColor *darkerColor = [self darkerColorForColor:baseColor];
EDIT: as #Anchu Chimala pointed out, for maximum flexibility, these methods should be implemented as an UIColor category. Also, from #Riley's idea, it may be a better idea to make the color proprtionally darker or lighter instead of adding or subtracting constant values. As #jrturton pointed out, it's not necessary to manipulate the RGB components; it's better to modify the brightness property itself. All in all:
#implementation UIColor (LightAndDark)
- (UIColor *)lighterColor
{
CGFloat h, s, b, a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
return [UIColor colorWithHue:h
saturation:s
brightness:MIN(b * 1.3, 1.0)
alpha:a];
return nil;
}
- (UIColor *)darkerColor
{
CGFloat h, s, b, a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
return [UIColor colorWithHue:h
saturation:s
brightness:b * 0.75
alpha:a];
return nil;
}
#end
TL;DR:
Swift:
extension UIColor {
var lighterColor: UIColor {
return lighterColor(removeSaturation: 0.5, resultAlpha: -1)
}
func lighterColor(removeSaturation val: CGFloat, resultAlpha alpha: CGFloat) -> UIColor {
var h: CGFloat = 0, s: CGFloat = 0
var b: CGFloat = 0, a: CGFloat = 0
guard getHue(&h, saturation: &s, brightness: &b, alpha: &a)
else {return self}
return UIColor(hue: h,
saturation: max(s - val, 0.0),
brightness: b,
alpha: alpha == -1 ? a : alpha)
}
}
Usage:
let lightColor = somethingDark.lighterColor
Objective-C:
- (UIColor *)lighterColorRemoveSaturation:(CGFloat)removeS
resultAlpha:(CGFloat)alpha {
CGFloat h,s,b,a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
return [UIColor colorWithHue:h
saturation:MAX(s - removeS, 0.0)
brightness:b
alpha:alpha == -1? a:alpha];
}
return nil;
}
- (UIColor *)lighterColor {
return [self lighterColorRemoveSaturation:0.5
resultAlpha:-1];
}
#rchampourlier was right in his comment to #user529758 (The accepted answer) - The HSB (Or HSV) and RGB solutions give completely different results. RGB just adds (Or makes the color closer to) white, and the HSB solution brings the color closer to the edge in the Brigtness scale - which basically start with black and ends with the pure color...
Basically Brightness (Value) makes the color less or more closer to black, where Saturation makes it less or more closer to white...
As seen here:
So the solution to make a color actually brighter (i.e. closer to white...) will be to make it's Saturation value smaller, resulting this solution:
- (UIColor *)lighterColor {
CGFloat h,s,b,a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
return [UIColor colorWithHue:h
saturation:MAX(s - 0.3, 0.0)
brightness:b /*MIN(b * 1.3, 1.0)*/
alpha:a];
}
return nil;
}
Swift universal extension for iOS and OS X, using getHue :
#if os(OSX)
import Cocoa
public typealias PXColor = NSColor
#else
import UIKit
public typealias PXColor = UIColor
#endif
extension PXColor {
func lighter(amount : CGFloat = 0.25) -> PXColor {
return hueColorWithBrightnessAmount(1 + amount)
}
func darker(amount : CGFloat = 0.25) -> PXColor {
return hueColorWithBrightnessAmount(1 - amount)
}
private func hueColorWithBrightnessAmount(amount: CGFloat) -> PXColor {
var hue : CGFloat = 0
var saturation : CGFloat = 0
var brightness : CGFloat = 0
var alpha : CGFloat = 0
#if os(iOS)
if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
return PXColor( hue: hue,
saturation: saturation,
brightness: brightness * amount,
alpha: alpha )
} else {
return self
}
#else
getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
return PXColor( hue: hue,
saturation: saturation,
brightness: brightness * amount,
alpha: alpha )
#endif
}
}
Usage :
let color = UIColor(red: 0.5, green: 0.8, blue: 0.8, alpha: 1.0)
color.lighter(amount:0.5)
color.darker(amount:0.5)
OR (with the default values):
color.lighter()
color.darker()
Sample :
I just wanted to give the same result, in RGB, than
placing the color with alpha x% over a white background to lighten
placing the color with alpha x% over a black background to darken
Which gives the same result, AFAIK, than picking the color in a gradient 'color to white' or 'color to black', at x% of the gradient size.
For that purpose, the math is simple:
extension UIColor {
func mix(with color: UIColor, amount: CGFloat) -> UIColor {
var red1: CGFloat = 0
var green1: CGFloat = 0
var blue1: CGFloat = 0
var alpha1: CGFloat = 0
var red2: CGFloat = 0
var green2: CGFloat = 0
var blue2: CGFloat = 0
var alpha2: CGFloat = 0
getRed(&red1, green: &green1, blue: &blue1, alpha: &alpha1)
color.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha2)
return UIColor(
red: red1 * (1.0 - amount) + red2 * amount,
green: green1 * (1.0 - amount) + green2 * amount,
blue: blue1 * (1.0 - amount) + blue2 * amount,
alpha: alpha1
)
}
}
Here are examples with some colors
user529758's solution in Swift:
Darker color:
func darkerColorForColor(color: UIColor) -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if color.getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
}
return UIColor()
}
Lighter color:
func lighterColorForColor(color: UIColor) -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if color.getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
}
return UIColor()
}
If you convert the RGB color to the HSL color model then you can vary the L = lightness component from L = 0.0 (black) over L = 0.5 (natural color) to L = 1.0 (white) . UIColor cannot handle HSL directly, but there are formula for converting RGB <-> HSL.
All other answers in this thread use either the RGB color system or simply change the hue or brightness value of the HSB system. As explained in detail in this great blog post the correct way of making a color lighter or darker is to change its luminance value. None of the other answers does that. If you want to do it right, then use my solution or write your own after reading the blog post.
Unfortunately it's quite a hassle to change any of the attributes of a UIColor by default. Also Apple doesn't even support any LAB-based color space like HCL in the UIColor class (the L in LAB is the luminance value we are looking for).
Using HandyUIKit (install it via Carthage) adds support for HCL and makes your life a lot easier:
import HandyUIKit
let color = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)
// create a new UIColor object with a specific luminance (slightly lighter)
color.change(.luminance, to: 0.7)
There is also an option to apply a relative change (recommended):
// create a new UIColor object with slightly darker color
color.change(.luminance, by: -0.2)
Note that HandyUIKit also adds some other handy UI features into your project – checkout its README on GitHub for more details.
I hope it helps!
Disclaimer: I'm the author of HandyUIKit.
None of the solutions posted quite worked for all colours and shades, but then I stumbled across this library which provides a set of very well implemented extensions to UIColor.
Specifically it has a lighten function as part of its HSL implementation: (UIColor *)lighten:(CGFloat)amount - which works perfectly.
Sebyddd solution as an extension:
extension UIColor {
func darker() -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if self.getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
}
return UIColor()
}
func lighter() -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if self.getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
}
return UIColor()
}
}
Usage:
let darkerYellow = UIColor.yellow.darker()
let lighterYellow = UIColor.yellow.lighter()
Swift 5
extension UIColor {
func lighter(by percentage:CGFloat=30.0) -> UIColor? {
return self.adjust(by: abs(percentage) )
}
func darker(by percentage:CGFloat=30.0) -> UIColor? {
return self.adjust(by: -1 * abs(percentage) )
}
func adjust(by percentage:CGFloat=30.0) -> UIColor? {
var r:CGFloat=0, g:CGFloat=0, b:CGFloat=0, a:CGFloat=0;
if self.getRed(&r, green: &g, blue: &b, alpha: &a) {
return UIColor(red: min(r + percentage/100, 1.0),
green: min(g + percentage/100, 1.0),
blue: min(b + percentage/100, 1.0),
alpha: a)
} else {
return nil
}
}
}
If you want user529758's solution to work with gray shades (like [UIColor lightGrayColor] or [UIColor darkGrayColor] you have to improve it like that:
- (UIColor *)lighterColor
{
CGFloat h, s, b, a;
if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
return [UIColor colorWithHue:h
saturation:s
brightness:MIN(b * 1.3, 1.0)
alpha:a];
}
CGFloat white, alpha;
if ([self getWhite:&white alpha:&alpha]) {
white = MIN(1.3*white, 1.0);
return [UIColor colorWithWhite:white alpha:alpha];
}
return nil;
}
getHue:saturation:brightness:alpha fails (and returns false) when called on a gray shade therefore you'll need to use getWhite:alpha.
UIColor extension and fixing lighterColorForColor
extension UIColor {
class func darkerColorForColor(color: UIColor) -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if color.getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
}
return UIColor()
}
class func lighterColorForColor(color: UIColor) -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if color.getRed(&r, green: &g, blue: &b, alpha: &a){
let tmpColor = UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
println(tmpColor)
return tmpColor
}
return UIColor()
}
}
I'm not sure if you're looking for some sort of Objective-C answer, but based on how colors specified by RGBA work, I think you can simply scale the RGB values according to an arbitrary factor to get a "lighter" or "darker" shade. For example, you might have a blue:
[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];
Want a darker blue? Multiply the RGB values by 0.9:
[UIColor colorWithRed:0.0 green:0.0 blue:0.9 alpha:1.0];
Voila. Or maybe you have an orange:
[UIColor colorWithRed:1.0 green:0.4 blue:0.0 alpha:1.0];
Choose another scale factor, say, 0.8:
[UIColor colorWithRed:0.8 green:0.32 blue:0.0 alpha:1.0];
Is that the sort of effect you're looking for?
Tested in Xcode 10 with Swift 4.x for iOS 12
Start with your color as a UIColor and pick a darkening factor (as a CGFloat)
let baseColor = UIColor.red
let darkenFactor: CGFloat = 2
The type CGColor has an optional value components which break down the color into RGBA (as a CGFloat array with values between 0 and 1). You can then reconstruct a UIColor using RGBA values taken from the CGColor and manipulate them.
let darkenedBase = UIColor(displayP3Red: startColor.cgColor.components![0] / darkenFactor, green: startColor.cgColor.components![1] / darkenFactor, blue: startColor.cgColor.components![2] / darkenFactor, alpha: 1)
In this example, each of the RGB valuse were divided by 2, making the color half as dark as it was before. The alpha value remained the same, but you could alternatively apply the darken factor on the alpha value rather than the RGB.
Ideally, the functions should be encapsulated inside a UIColor extension called, UIColor+Brightness.swift, and have a configurable brightness - see example below:
import UIKit
extension UIColor {
func lighterColorWithBrightnessFactor(brightnessFactor:CGFloat) -> UIColor {
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if self.getRed(&r, green:&g, blue:&b, alpha:&a) {
return UIColor(red:min(r + brightnessFactor, 1.0),
green:min(g + brightnessFactor, 1.0),
blue:min(b + brightnessFactor, 1.0),
alpha:a)
}
return UIColor()
}
}
I render coloured cells based on a status value:
For this I wrote a swift extension based on some old objc code after I got an error using CryingHippo's suggestion:
extension UIColor{
func darker(darker: CGFloat) -> UIColor{
var red: CGFloat = 0.0
var green: CGFloat = 0.0
var blue: CGFloat = 0.0
if self.colorSpace == UIColorSpace.genericGrayColorSpace(){
red = whiteComponent - darker
green = whiteComponent - darker
blue = whiteComponent - darker
} else {
red = redComponent - darker
green = greenComponent - darker
blue = blueComponent - darker
}
if red < 0{
green += red/2
blue += red/2
}
if green < 0{
red += green/2
blue += green/2
}
if blue < 0{
green += blue/2
red += blue/2
}
return UIColor(
calibratedRed: red,
green: green,
blue: blue,
alpha: alphaComponent
)
}
func lighter(lighter: CGFloat) -> UIColor{
return darker(-lighter)
}
}
The same works for NSColor as well. Simply replace UIColor with NSColor.
Here is a UIColor category that also allows control over the amount of color change.
- (UIColor *)lighterColorWithDelta:(CGFloat)delta
{
CGFloat r, g, b, a;
if ([self getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MIN(r + delta, 1.0)
green:MIN(g + delta, 1.0)
blue:MIN(b + delta, 1.0)
alpha:a];
return nil;
}
- (UIColor *)darkerColorWithDelta:(CGFloat)delta
{
CGFloat r, g, b, a;
if ([self getRed:&r green:&g blue:&b alpha:&a])
return [UIColor colorWithRed:MAX(r - delta, 0.0)
green:MAX(g - delta, 0.0)
blue:MAX(b - delta, 0.0)
alpha:a];
return nil;
}
A Swift extension based on #Sebyddd answer:
import Foundation
import UIKit
extension UIColor{
func colorWith(brightness: CGFloat) -> UIColor{
var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
if getRed(&r, green: &g, blue: &b, alpha: &a){
return UIColor(red: max(r + brightness, 0.0), green: max(g + brightness, 0.0), blue: max(b + brightness, 0.0), alpha: a)
}
return UIColor()
}
}
for darker color, this is the simplest:
theColor = [theColor shadowWithLevel:s]; //s:0.0 to 1.0

Setting custom color on UINavaigationBar

Is it possible to set color of UINavigationBar with particular opacity and alpha? I've tried a lot things, but I still can't get what I want. The color is 7, 4, 43 for RGB and 0,4 for opacity and alpha.
I think this should work for you:
[navigationBar setBarTintColor:[UIColor colorWithRed:7.0/255.0 green:4.0/255.0 blue:43.0/255.0 alpha:0.4]];
And in Swift:
navigationBar.barTintColor = UIColor(red: 7.0, green: 4.0, blue: 43.0, alpha: 0.4)