Changing color of NSView - swift

I'm creating a simple Custom NSView that allows the user to input 3 text fields each for R,G and B values respectively. I already referenced this question and answer set here - it only accounts up to Swift 2.0. So, does anyone know the correct technique of obtaining this same effect in Swift 3.0? I can't seem to get anything that I'm doing to work. I keep getting errors of all sorts.
Here's the current technique I'm using (This seems to work... BUT it won't account for the other 2 RGB values, since it's used in the #IBAction):
//viewDidLoad
RVCustomView.wantsLayer = true
#IBAction func redValue(_ sender: AnyObject) {
print(red.stringValue)
var rValue = 0
let str = red.stringValue
if let n = NumberFormatter().number(from: str) {
rValue = Int(CGFloat(n))
}
CustomNSView.layer?.backgroundColor = CGColor(red: rValue, green: 255, blue: 255, alpha: 255)
}

If you want to dynamically change the background colour of a NSView each time the value of one of the three R, G, B text views changes, you could use the controlTextDidChange(notification:) delegate method of NSTextField coupled with outlets for each of the three text fields.
The method is fired every time one of the fields is changed and you use it for reading the value of the RGB fields (via outlets) and change the colour accordingly.
override func controlTextDidChange (notification: NSNotification?) {
// assuming the text fields' value is between 0 and 255
guard
let redValue = Float(redOutlet.stringValue),
let greenValue = Float(greenOutlet.stringValue),
let blueValue = Float(blueOutlet.stringValue)
else { return }
CustomNSView.layer?.backgroundColor = CGColor(red: CGFloat(redValue/255), green: CGFloat(greenValue/255), blue: CGFloat(blueValue/255), alpha: 255)
}
Note : don't forget to properly set the delegate for each of the three text fields!

I think you can just do that:
#IBAction func redValue(_ sender: AnyObject) {
yourView.backgroundColor = UIColor(colorLiteralRed: readValue/255, green: greenValue/255, blue: blueValue/255, alpha: 1)
}

Related

How can I get a slider to change the background color in Swift?

I'm trying to create a flashlight app for school and I wanted to add a slider to change the background from black to white. I can't seem to be able to figure it out.
I've tried some basic things, but nothing I've seen online works. It's either out of date or I'm just not understanding something.
So first you should get slidder value by creating an #IBAction for its value change and then using it to adjust the color of the background
override func viewDidLoad() {
slider.minimumValue = 0.0
slider.maximumValue = 255.0
}
#IBAction func sliderValueChanged(_ sender: UISlider) {
let currentValue = Int(sender.value)
let backgroundColor = UIColor(
red: CGFloat(currentValue),
green: CGFloat(currentValue),
blue: CGFloat(currentValue),
alpha:1.0
)
self.view.backgroundColor = backgroundColor
}
Assuming you want to use a switch. You can make an if-else statement and change the color of the view based on if the switch is enabled or not. This would be an instant change, not a gradual change.
#IBAction func `switch`(_ sender: Any) {
if ((sender as AnyObject).isOn == true){
view.backgroundColor = UIColor.white
} else {
view.backgroundColor = UIColor.black
}
}

iOS 13 system color for UIButton

Apple recommends using system colors to adapt apps to light and dark mode automatically, for example:
myLabel.textColor = UIColor.secondaryLabel
Here Apple lists various properties to be used, such as the one in the example above, and system colors for background, placeholder text, and more.
But it doesn't list a property for UIButton elements.
Which property or other method should we use to adapt UIButtons to theme changes?
As of now, I'm doing this:
myButton.tintColor = UIColor.link
which is supposedly for links but is the only "clickable" property I found.
I'm not looking to use something like UIColor.systemRed, rather something like UIColor.systemBackground, which adapts automatically to the current theme.
I hope you create colored Assets not one by one. You can use this function to tint images as a extension of UIImageView. I also use the same technique for buttons.
func setImageAndColor(image: UIImage, color: UIColor) {
let templateImage = image.withRenderingMode(.alwaysTemplate)
self.image = templateImage
self.tintColor = color
}
In case you want to define all you own colors, I suggest to create a singleton class named Colors:
import UIKit
class Colors {
static let shared = Colors()
var statusBarStyle: UIStatusBarStyle = .lightContent
private init(){}
func setLightColors() {
statusBarStyle = .darkContent
yourColor = UIColor( // choose your favorite color
styleColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1)//white
labelColor = UIColor(red: 15/255, green: 15/255, blue: 15/255, alpha: 1)
subLabelColor = UIColor(red: 25/255, green: 25/255, blue: 25/255, alpha: 1)
............ set values for all colors from here.
}
func setDarkColors() {
statusBarStyle = .lightContent
yourColor = // choose your favorite color
............
}
// set initial colors
var yourColor: UIColor =
}
If somebody is interested in the whole Colors class, text me or comment below.
I access the colors singleton by:
Colors.shared.yourColor
Also for first configuration I set in the very first VC the darkmode number (0-Auto; 1-On; 2-Off):
if darkmodeNumber == 0 {
if traitCollection.userInterfaceStyle == .light {
print("Light mode")
Colors.shared.setLightColors()
} else {
print("Dark mode")
Colors.shared.setDarkColors()
}
} else if darkmodeNumber == 1 {
Colors.shared.setDarkColors()
} else if modeNumber == 2 {
Colors.shared.setLightColors()
}
}
The statusbar should then change also the right way.
Use any system colors you like. They are all adaptive. I applied the system gray color to a button's text:
The color changes when we switch between light and dark mode.

How to store a color label in Xcode 10.2.1 from iOS 9.3

I'm making a game, and I want to save that when I pass the level, the background of the button changes color. Is it correct to use UserDefaults?
For example, the button "level 1" the background is gray and when the level is completed the color changes to orange but when I close the app, the button "level 1" returns to its gray color.
How do I save the color of the button in this case orange when the level is completed?
I've tried to use userDefaults but when defining it it tells me "UIColor cannot be converted to String"
#IBAction func continuarAccion(_ sender: Any) {
animateOut(desireView: vistaNivel1). //Remove the view, in this case I have a blur, is where the level is shown
botonNivel1.backgroundColor = UIColor.white
}
By default, the background button "level 1", is white
when the level is complete the "level 1 button" changes the background to orange.
I would like to know how I can save that orange color so that when I close the app, the background of the "level 1" button remains orange.
Is it correct for me to use Userefaults?
I'm using xcode 10.1.2, compatibility from iOS 9.3
save hex value to userdefaults:
UserDefaults.standard.set( hexValue as? String, forKey: "color")
// get value
let strColor = UserDefaults.standard.object(forKey: "color") as? String
// To convert hex value to UIColor:
func hexStringToUIColor (hex:String) -> UIColor {
var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
if (cString.hasPrefix("#")) {
cString.remove(at: cString.startIndex)
}
if ((cString.count) != 6) {
return UIColor.gray
}
var rgbValue:UInt32 = 0
Scanner(string: cString).scanHexInt32(&rgbValue)
return UIColor(
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}

When multiple NSTextViews are present in a window, the one receiving typed keys isn't necessarily the one receiving command-keys. Why?

I am having a hard time understanding the responder chain in OS X.
I have an NSTextView subclass, and I want it to respond to a command-key and do something. I've created a very simple demonstration of my problem. Anyone interested can see if with only a couple minute's effort.
Create a new OS X project, and here is the only additional code you need. Make a new class in Swift named MyTextView (subclass of NSTextView) and paste this into it:
import Cocoa
class MyTextView: NSTextView {
// listen for a command key
override func performKeyEquivalent(theEvent: NSEvent) -> Bool {
// if it's a cmd-equals, change the background
if theEvent.characters == "=" && theEvent.modifierFlags.contains(.CommandKeyMask) {
Swift.print(theEvent)
self.backgroundColor = NSColor(calibratedRed: CGFloat(arc4random()) / CGFloat(UInt32.max),
green: CGFloat(arc4random()) / CGFloat(UInt32.max),
blue: CGFloat(arc4random()) / CGFloat(UInt32.max),
alpha: 1.0)
return true
}
return super.performKeyEquivalent(theEvent)
}
}
Now in your storyboard, place 2 or more NSTextViews into the same contentView. Under the Identity Inspector, tell each NSTextView its class is MyTextView (the NSTextView is nested a bit: NSScrollView > NSClipView > NSTextView).
Run the project. Hit cmd-equal. One of the textviews changes its background color, but it isn't necessarily the one that possesses the cursor, which is receiving all the other key-presses. It isn't necessarily the one that starts out with the cursor. And if you place the cursor in a different textView, it still doesn't change which one responds to the command key.
Why is that? Why isn't the textview that's receiving the typed keystrokes the same textview that's receiving the command-keys? Clearly the textviews know who is supposed to be receiving the keystrokes, because typing works. But my command-key goes to somebody else.
Here is the solution. MyTextView needs to test whether it is the FirstResponder. If it is, it consumes the event. If it isn't, it doesn't.
override func performKeyEquivalent(theEvent: NSEvent) -> Bool {
if self.window?.firstResponder == self {
// if it's a cmd-equals, change the background
if theEvent.characters == "=" && theEvent.modifierFlags.contains(.CommandKeyMask) {
Swift.print(theEvent)
self.backgroundColor = NSColor(calibratedRed: CGFloat(arc4random()) / CGFloat(UInt32.max),
green: CGFloat(arc4random()) / CGFloat(UInt32.max),
blue: CGFloat(arc4random()) / CGFloat(UInt32.max),
alpha: 1.0)
return true
}
}
return super.performKeyEquivalent(theEvent)
}

re-rolling a random number in swift

So, while working in swift, i made a view in a viewController where when I tap another view in the same ViewController, it generates an array with value
[arc4random_uniform(257), arc4random_uniform(257), arc4random_uniform(257)]
where the random numbers are parameters for random RBG colors, and I've only sort-of made it work. I want it so that every time the user (or me ;_;) taps on the view with the Tap Gesture Recognizer, it generates another random color. I don't really know how to "re-roll" the Array so that it generates another random color.
If you want to get just a random UIColor, you can create a function which gets called everytime you touch the recognizer. Also, as mattt mentioned in the comments, you should change the max value from 257 to 256.
func randomColorCreator()->UIColor{
var red:CGFloat = CGFloat(arc4random_uniform(256))/CGFloat(255)
var green:CGFloat = CGFloat(arc4random_uniform(256))/CGFloat(255)
var blue:CGFloat = CGFloat(arc4random_uniform(256))/CGFloat(255)
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
If you really want to get the three color-values, you can return the three values like that:
func randomColorCreatorV2()->(red:Int, green:Int, blue:Int){
var red: = arc4random_uniform(256)
var green: = arc4random_uniform(256)
var blue: = arc4random_uniform(256)
return (red, green, blue)
}
You than access the values like that in your TapGestureRecognizer method:
var randomColors = randomColorCreatorV2()
var blueValue = randomColors.blue