Light and dark mode in swift - swift

I created images assets for dark and light mode called myImage. Set the image assets appearance to Any, Dark.
The problem this code gets the same image even if the mode is light or dark.
How can I get the code to select the correct image depending on light or dark mode?
Thanks for your help.
let image = UIImage(named: "image")
let asset = image?.imageAsset
let resolvedImage = asset?.image(with: traitCollection)
If let image = resolvedImage {
myButton.setImage(image, for: .normal)
}

let image = UIImage(named: "image") is usually all that is needed, if you setup your asset correctly. Make sure to have "Appearances" set to "Any, Dark", then add your images in the appropriate slots:

Find out the current used dark/light mode with:
if traitCollection.userInterfaceStyle == .light {
print("Light mode")
} else {
print("Dark mode")
}
Then I'd access the light/dark Images with different name: UIImage:(named: "myImageLightMode") and UIImage:(named: "myImageDarkMode")
Keep in mind that you can tint images like button images in the desired color like the following, when you don't want to create each icon on a different color:
if let originalImage = UIImage(named: "yourButtonImage") {
let tintedImage = originalImage.withRenderingMode(.alwaysTemplate)
customButton.setImage(tintedImage, for: .normal)
customButton.tintColor = UIColor.red
} else {
print("Image not found.")
}
The same can be done on UIImageView's with the extension:
extension UIImageView {
func setImageAndColor(image: UIImage, color: UIColor) {
let templateImage = image.withRenderingMode(.alwaysTemplate)
self.image = templateImage
self.tintColor = color
}
}
access this with:
let imageView = UIImageView()
imageView.setImageAndColor(image: UIImage(named: "yourImage"), color: .red)

Related

Default Image Isn't Displaying When Setting Image

I am trying to set the default avatar image to a "ninja" image. Default image isn't showing however with this code. Not sure what is wrong.
ProfileService.showOtherUser(user: bet.sentToUser) { [weak self] (profile2) in
self?.profile2 = profile2
if (profile2?.imageURL == "") {
cell.userImage.image = UIImage(named: "ninja")
}else{
let imageURL = URL(string: ((profile2?.imageURL ?? "")))
cell.userImage.kf.setImage(with: imageURL)
}
}
}
Put your image in storyboard to your image view this way till you not change it programmatically it will remain the default one

Get and change hue of SKSpriteNode's SKColor(HSBA)?

A SKSpriteNode's SKColor has a way to be created with Hue, Saturation, Brightness & Alpha:
let myColor = SKColor(hue: 0.5, saturation: 1, brightness: 1, alpha: 1)
mySprite.color = myColor
How do I get at the hue of a SKSpriteNode and make a change to it? eg, divide it by 2.
An SKSpriteNode is a node that draws a texture (optionally blended with a color), an image, a colored square. So, this is it's nature.
When you make an SKSpriteNode, you have an instance property that represent the texture used to draw the sprite called also texture
Since iOS 9.x, we are able to retrieve an image from a texture following the code below. In this example I call my SKSpriteNode as spriteBg:
let spriteBg = SKSpriteNode.init(texture: SKTexture.init(imageNamed: "myImage.png"))
if let txt = spriteBg.texture {
if #available(iOS 9.0, *) {
let image : UIImage = UIImage.init(cgImage:txt.cgImage())
} else {
// Fallback on earlier versions and forgot this code..
}
}
Following this interesting answer, we can translate it to a more confortable Swift 3.0 version:
func imageWith(source: UIImage, rotatedByHue: CGFloat) -> UIImage {
// Create a Core Image version of the image.
let sourceCore = CIImage(cgImage: source.cgImage!)
// Apply a CIHueAdjust filter
guard let hueAdjust = CIFilter(name: "CIHueAdjust") else { return source }
hueAdjust.setDefaults()
hueAdjust.setValue(sourceCore, forKey: "inputImage")
hueAdjust.setValue(CGFloat(rotatedByHue), forKey: "inputAngle")
let resultCore = hueAdjust.value(forKey: "outputImage") as! CIImage!
let context = CIContext(options: nil)
let resultRef = context.createCGImage(resultCore!, from: resultCore!.extent)
let result = UIImage(cgImage: resultRef!)
return result
}
So, finally with the previous code we can do:
if let txt = spriteBg.texture {
if #available(iOS 9.0, *) {
let image : UIImage = UIImage.init(cgImage:txt.cgImage())
let changedImage = imageWith(source: image, rotatedByHue: 0.5)
spriteBg.texture = SKTexture(image: changedImage)
} else {
// Fallback on earlier versions or bought a new iphone
}
}
I'm not in a place to be able to test this right now, but looking at the UIColor documentation (UIColor and SKColor are basically the same thing), you should be able to use the .getHue(...) function retrieve the color's components, make changes to it, then set the SKSpriteNode's color property to the new value. the .getHue(...) function "Returns the components that make up the color in the HSB color space."
https://developer.apple.com/reference/uikit/uicolor/1621949-gethue

Colorize image, take the wrong color swift

I want to colorize an image from an imageView. After that I want to set this image to a button.
let imageView:UIImageView = UIImageView()
if let myImage = UIImage(named: "ic_star") {
let tintableImage = myImage.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = tintableImage
}
imageView.tintColor = UIColor.redColor()
bestListButton.setImage(imageView.image, forState: .Normal)
This is a snippet, that should work, but it colorize my button-image always in blue.
The debugger say that the color doesn't change. And the simulator change it in blue.
It seems that it doesn't have something to do with my backgroundcolor of image.
EDIT and (hack) solution
Okay, it's quite strange. The blue is because in my interface builder was the tintColor blue.
I changed it to white. Now my star is white.
BUT: When I delete my code, the image switch back to black. So the change of color seems just work in combination with interface builder and code.
EDIT 2
Programmatically solution:
bestListButton.tintColor = UIColor.redColor()
Is your image a PNG file?
Try:
let imageView:UIImageView = UIImageView()
if let myImage = UIImage(named: "ic_star") {
imageView.image = imageView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
}
imageView.tintColor = UIColor.redColor()
bestListButton.setImage(imageView.image, forState: .Normal)

swift UIButton.selected won't work

I'm trying to keep a button selected while its audio is being played. the problem is the button won't change unless I change it in a loop (while(audioPlayer.playing){button.selcted=true}). In this case I can't use the app until audio has finished(for obvious reasons)
hopefully someone can help me
func addButton(number: String, x:CGFloat, y:CGFloat){
let button = UIButton(type: UIButtonType.Custom) as UIButton
button.setTitle(number, forState: .Normal)
button.frame = CGRectMake(x, y, 68, 212)
if let image = UIImage(named: number) {
button.setImage(image, forState: .Normal)
}
button.addTarget(self, action: "play:", forControlEvents:.TouchUpInside)
self.view.addSubview(button)
}
#IBAction func play(sender: UIButton) {
button=sender
button.selected = true
let audioFilePath = NSBundle.mainBundle().pathForResource(sender.currentTitle, ofType: "WAV")
if audioFilePath != nil {
let audioFileUrl = NSURL.fileURLWithPath(audioFilePath!)
do { audioPlayer = try AVAudioPlayer(contentsOfURL: audioFileUrl, fileTypeHint: nil)} catch _ { return }
audioPlayer?.delegate = self
audioPlayer.play()
} else {
print("audio file is not found")
}
}
I just wrote up a test app to see what you are actually trying to do here, set sender.enabled = false is what you are looking for. (The button as an animation that goes to the faded out gray that is set by not enabled, then goes back to the original color of enabled, setting it to false prevents the second part from happening)
Edit: In the end, the results that were desired was an accessible button with the gray text, so we changed the text highlight state to a gray using sender.setTitleColor(UIColor.grayColor(),forState:.Highlighted) and the user will set the highlighted variable to true in the Play function.

changing colour of a Navigation Bar Button

I have a method to change the colour of an image. I use this colour icons in menus of my app quickly without having to go any create and image of the correct colour each time.
/// Tint an image with a selected colour.
///
/// - Parameters:
/// - image: The image you wish to colour
/// - imageView: The imageView containing the image
/// - colour: Colour you wish to tint image with. Set as nil if you dont want to change it or im image is multicoloured.
func tint(icon image:UIImage, for imageView:UIImageView, with colour:UIColor?) {
if colour != nil {
let template = image.withRenderingMode(.alwaysTemplate)
imageView.tintColor = colour!
imageView.image = template
} else {
imageView.image = image
}
}
This works fine most of the time. However my problem is trying to set the colour of an image in a navigation bar it doesn't work at all and the image stays its original colour.
I'm trying the following
let dashboardButton = UIButton(type: .custom)
let dashboardButtonImage = UIImage(named: "example image name")
dashboardButton.setImage(dashboardButtonImage.imageResize(sizeChange: CGSize(width: 20, height: 20)), for: .normal)
style.tint(icon: dashboardButtonImage, for: dashboardButton.imageView!, with: .red)
dashboardButton.contentHorizontalAlignment = .fill
dashboardButton.contentVerticalAlignment = .fill
dashboardButton.imageView?.contentMode = .scaleAspectFit
dashboardButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
dashboardButton.addTarget(self, action: #selector(ExampleViewController.goToDashboard), for: .touchUpInside)
let dashboardItem = UIBarButtonItem(customView: dashboardButton)
self.navigationItem.setRightBarButtonItems([dashboardItem], animated: false)
I could very easily fix the problem by just making a graphic of the correct colour. However I want to keep these colour changes in app for when a client decides the want to change colours. I'm wondering why I cant get it to work in the nav bar? Is there a fix for this?
There is always a problem accessing a buttons image property of its image view directly like this:
buttom.imageView.image = testImage
You could try this instead which works for me:
func tint(icon image: UIImage, for button: UIButton, with colour: UIColor?) {
if colour != nil {
let template = image.withRenderingMode(.alwaysTemplate)
button.setImage(template, for: .normal)
button.imageView!.tintColor = .red
} else {
button.setImage(image, for: .normal)
}
}
Using that you pass the button instead of the image view and the function uses the setImage method of UIButton to set it. That appears to get round the problem.