How to convert a UIColor to a black and white UIColor - swift

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

Related

How to save a Color in the #AppStorage in SwiftUi

I want to save a Color value in the #AppStorage but I get an error. How can I fix it?
#AppStorage ("selectedColor") var selectedColor: Color = .teal
save color as string
#AppStorage ("selectedColor") var selectedColor: String = ""
create a function that transforms the color into a string
func updateCardColorInAppStorage(color: Color)-> String {
let uiColor = UIColor(color)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return "\(red),\(green),\(blue),\(alpha)"
}
and String to Color
if (cardColor != "" ) {
let rgbArray = cardColor.components(separatedBy: ",")
if let red = Double (rgbArray[0]), let green = Double (rgbArray[1]), let blue = Double(rgbArray[2]), let alpha = Double (rgbArray[3]){ bgColor = Color(.sRGB, red: red, green: green, blue: blue, opacity: alpha)
}

black color in function always, why?

I want my text to get random color, for that I made a function but I do get always black color, this function should return a random color for me.
struct ContentView: View {
#State var colorOfText = randomColorFunction()
var body: some View {
Text("Hello, world!").font(Font.largeTitle.bold()).foregroundColor(colorOfText)
}
}
func randomColorFunction() -> Color {
let redValue = UInt8.random(in: 0...255)
let greenValue = UInt8.random(in: 0...255)
let blueValue = UInt8.random(in: 0...255)
print(redValue.description, greenValue.description, blueValue.description)
return Color(red: Double(redValue/255), green: Double(greenValue/255), blue: Double(blueValue/255))
}
You need to change the return of randomColorFunction to this:
return Color(red: Double(redValue)/255.0, green: Double(greenValue)/255.0, blue: Double(blueValue)/255.0)
your solution did not work, because the result of the division always return Int and it causes to be 0 or 1 that means black color or white color
Your code is creating UInt8 values, and dividing them by the int value of 255. The result will always be an integer of 0 or 1. (and the odds are it will be 0 about 255 out of 256 times.)
You need to either use Double.random(in: 0.0...1.0) as suggested by Vadian, or cast your values to doubles:
let redValue = Double(Int.random(in: 0...255))
let greenValue = Double(Int.random(in: 0...255))
let blueValue = Double(Int.random(in: 0...255))
print(redValue.description, greenValue.description, blueValue.description)
return Color(
red: Double(redValue/255.0),
green: Double(greenValue/255.0),
blue: Double(blueValue/255.0))

Can UIColor be initialised with both dark and light mode color?

I am using random pastel colours in my training app (bouncing circles), but when my iPad is in dark mode, the pastels looks very bland. Can I somehow initialise UIColor with two colours? Maybe something like:
UIColor(forLightMode: UIColor, forDarkMode: UIColor)
My current app is creating new colours properly, but they do not change automatically, when I change from dark to light mode. The app is just starting to generate new ones from pastel set.
func makeRandomColor() -> UIColor {
let fullRange : ClosedRange<CGFloat> = 0...255
let pastelRange : ClosedRange<CGFloat> = 127...255
let randomPastelRed = CGFloat.random(in: pastelRange) / 255
let randomPastelGreen = CGFloat.random(in: pastelRange) / 255
let randomPastelBlue = CGFloat.random(in: pastelRange) / 255
let randomRed = CGFloat.random(in: fullRange) / 255
let randomGreen = CGFloat.random(in: fullRange) / 255
let randomBlue = CGFloat.random(in: fullRange) / 255
let randomAlpha = CGFloat.random(in: 0.6...1)
return UIColor.init(dynamicProvider: { traitCollection in
if traitCollection.userInterfaceStyle == .dark {
return UIColor(
red: randomRed,
green: randomGreen,
blue: randomBlue,
alpha: randomAlpha
)
} else {
return UIColor(
red: randomPastelRed,
green: randomPastelGreen,
blue: randomPastelBlue,
alpha: randomAlpha
)
}
})
}
You'd need to listen to traitCollectionDidChange notification and redraw your UI either by calling setNeedsLayout() or similar methods from your UIView or UIViewController. For more Information check Implementing Dark Mode on iOS ~22min
You can do something like this:
var dynamicColor = UIColor {(traitCollection: UITraitCollection) -> UIColor in
if traitCollection.userInterfaceStyle == .dark {
return .white
} else {
return .black
}
}
Taken from a Screencast course on Ray Wenderlich (I'm not affiliated with the website): https://www.raywenderlich.com/3979883-dark-mode-deep-dive

Convert UIColor initialization to Color Literal Xcode

I have multiple different UIColor objects. Some of them are initialized by a constructor some of them are shown as color literals.
static let optionsHeader = UIColor([ ]) // XCode is showing a color rect.
static let optionButtonSelected = UIColor(red: 0.865, green: 0.804, blue: 0.0, alpha: 1.0)
How can I convert the UIColor.init(...) statements to a color literal.
RGB color literal is same as UIColor initialization:
#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
Or you can select color after typing #colorLiteral().
You can also use extensions to use hex color instead of inputting rgba values
extension UIColor {
convenience init(hexString: String, alpha: CGFloat = 1.0) {
let hexString: String = hexString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
let scanner = Scanner(string: hexString)
if (hexString.hasPrefix("#")) {
scanner.scanLocation = 1
}
var color: UInt32 = 0
scanner.scanHexInt32(&color)
let mask = 0x000000FF
let r = Int(color >> 16) & mask
let g = Int(color >> 8) & mask
let b = Int(color) & mask
let red = CGFloat(r) / 255.0
let green = CGFloat(g) / 255.0
let blue = CGFloat(b) / 255.0
self.init(red:red, green:green, blue:blue, alpha:alpha)
}
func toHexString() -> String {
var r:CGFloat = 0
var g:CGFloat = 0
var b:CGFloat = 0
var a:CGFloat = 0
getRed(&r, green: &g, blue: &b, alpha: &a)
let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0
return String(format:"#%06x", rgb)
}
}
Then you can code it with:
self.backgroundColor = UIColor(hexString: "#4A4A4A")

Set random color for a cgfill in external function

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())