How do I change the transparency of an NSImage/NSImageView? - swift

I have a view in the menu bar into which I'm putting some images. I want to make it 50% transparent. I've tried:
let image = NSImage(named: "bar.pdf")
let imageView = NSImageView(frame: NSRect(x: 0, y: 0, width: 3, height: 11))
imageView.wantsLayer = true
imageView.alphaValue = 0.5
However, the image is still completely opaque.

The following snippet appears to be working in the playground. Is it possible that you are actually setting the alphaValue of one view but showing another? Also, setting the alphaValue of the view does not in its own right call for wantsLayer to be true. Finally, your code example is missing the line where you set the image of the view, though I cannot imagine how that could be relevant to your problem (the order in which you set these two properties does not matter)...
import XCPlayground
import Cocoa
let url = NSURL(string: "http://www.gravatar.com/avatar/cbfa20635c9269675d54547c080c9b64")!
let image = NSImage(contentsOfURL: url)!
let imageView = NSImageView(frame: CGRect(origin: .zero, size: image.size))
imageView.image = image
imageView.alphaValue = 0.5
XCPlaygroundPage.currentPage.liveView = imageView

Apple changed some of the names of things in newer versions of swift:
Here's a Swift 3.0 version:
let url = URL(string: "http://www.gravatar.com/avatar/cbfa20635c9269675d54547c080c9b64")!
let image = NSImage(contentsOf: url)!
let imageView = NSImageView(frame: CGRect(origin: .zero, size: image.size))
imageView.image = image
imageView.alphaValue = 0.5
PlaygroundPage.current.liveView = imageView

Related

Generated Thumbnail won't set as UIButton Background Color

I recently came back to test a view controller which previously worked and took a locally saved video file, created a thumbnail from that file, and displayed the thumbnail as the background color of a UIButton using testButton.backgroundColor = UIColor(patternImage: image!) where image = generateThumbnail(). Now, for some reason, when I'm trying to cast the image as a pattern for the background color, the background color turns black, no image.
If I use an asset such as UIColor(patternImage: (UIImage(named: "Picture")) (instead of the UIImage generated from generateThumbnail()) the background color is set to the image, as expected.
Below is my generateThumbnail()
private func generateThumbnail(url: URL) -> UIImage? {
let videoAsset : AVAsset = AVAsset(url: url)
let assetImageGenerator : AVAssetImageGenerator = AVAssetImageGenerator(asset: videoAsset)
assetImageGenerator.appliesPreferredTrackTransform = true
var time = videoAsset.duration
time.value = min(time.value, 2)
do{
let thumbnail = try assetImageGenerator.copyCGImage(at: time, actualTime: nil)
let framedThumbnail : UIImage = UIImage(cgImage: thumbnail)
return framedThumbnail
} catch {
print("Error saving thumbnail \(error.localizedDescription)")
return nil
}
}
Here's an example of passing in UIImage to backgroundColor - which yields a black background
let urlTest = Bundle.main.url(forResource: "SampleVideo", withExtension: "mp4")!
let image = generateThumbnail(url: urlTest)
let testButton = UIButton()
testButton.frame = CGRect(x: 0, y: 0, width: 400, height: 300)
testButton.backgroundColor = UIColor(patternImage: image!)
An example of loading local image from assets file - yields correctly, image set as background for button:
let image = UIImage(named: "Sample")
let testButton = UIButton()
testButton.frame = CGRect(x: 0, y: 0, width: 400, height: 300)
testButton.backgroundColor = UIColor(patternImage: image!)
And yes, the urlTest does generate an image when run through generateThumbnail. I can get it to display in a test UIImageView() as expected, not sure why it turns black when set as backgroundColor
tl;dr
Why does my created thumbnail image not display as background for button when asset images will?
EDIT: Solved The Problem
Use the .setBackgroundImage method on UIButton. Solved example:
let urlTest = Bundle.main.url(forResource: "SampleVideo", withExtension: "mp4")!
let image = generateThumbnail(url: urlTest)
let testButton = UIButton()
thumbButton.setBackgroundImage(image, for: .normal)
I don't recall seeing that method as an option on UIButton before, may be new in Swift 5 ¯\_(ツ)_/¯

How do I change the color of an SF Symbols icon in Swift?

I realize this question has been asked here twice but none of the solutions provided are working for me. My icon is showing up but it is showing with a blue outline rather than the red I have requested. Swift is telling me that setting the foreground color is not an option
let largeConfig = UIImage.SymbolConfiguration(pointSize: heartPointSize)
let emptyHeartIcon = UIImage(systemName: "heart", withConfiguration:largeConfig)?.withTintColor(.systemRed) // this did not work
emptyHeartIcon?.withTintColor(.systemRed) // this also did not work
emptyHeartIcon!.withTintColor(.systemRed) // thought maybe it was because I wasn't unwrapping it but this also didn't work
If you're so inclined here's the context of the symbol :)
func levelUpsShown(){
let levelUpShownStackView = UIStackView(arrangedSubviews: [])
levelUpShownStackView.frame = CGRect(x: 15, y: 15, width: levelUpsShownView.bounds.width - 30, height: levelUpsShownView.bounds.height - 30)
let heartPointSize = (levelUpsShownView.bounds.width - 30)/8
let heartLocation = (levelUpsShownView.bounds.width - 38)/12
(0..<6).forEach { (levelUpsBucket) in
let largeConfig = UIImage.SymbolConfiguration(pointSize: heartPointSize)
let emptyHeartIcon = UIImage(systemName: "heart", withConfiguration: largeConfig)
let emptyHeartView = UIImageView(image: emptyHeartIcon)
let levelUpSegment = UIView()
levelUpSegment.addSubview(emptyHeartView)
emptyHeartView.center = CGPoint(x: heartLocation, y: 40)
levelUpShownStackView.addArrangedSubview(levelUpSegment)
}
levelUpShownStackView.distribution = .fillEqually
levelUpShownStackView.spacing = 4
levelUpsShownView.addSubview(levelUpShownStackView)
}
Try to change the tint of the UIImageView instead of the UIImage.
emptyHeartView.tintColor = .systemRed
If you don't want an UIImageView, check this post;
https://stackoverflow.com/a/19152722/8258494
Basically applying a mask on your image.

How to change the size of the titleView of Navigation Item? (Swift)

In my app I want to change the titleView of my Navigation Controller to a custom ImageView but I have a very strange problem. I basically just can`t set the frame of my ImageView.
This is my code:
func NavBarEinrichten(){
let logo = UIImage(named: "Notennamen für Griffe 1")!
let imageView = UIImageView(image:logo)
imageView.contentMode = .scaleAspectFit
//To show the problem better
imageView.backgroundColor = UIColor.red
let navController = navigationController!
let bannerWidth:CGFloat = 20
let bannerHeight:CGFloat = navController.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - logo.size.width / 2
let bannerY = bannerHeight / 2 - logo.size.height / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
self.navigationItem.titleView?.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
navigationItem.titleView = imageView
print(imageView.frame, "imageView frame")
}
The print statement prints:
(0.0, 0.0, 357.0, 142.0) imageView frame
Which is right, because it looks like this when i run it, but not like it should be. Because I want the width to be 20.
In the simulator it looks like this:
I tried to call this method in viewDidLoad(), viewWillAppear()and viewDidLayoutSubviews()
Every time with the exact same outcome...
Can you help me?

Insert CAShapeLayer behind Image in UIImageView

Just as the title says. I have a UIImageView and I am inserting CAShapeLayers into the View. The issue is that I don't know how to insert them behind the image of the UIImageView. Any advice would be much appreciated, thanks.
You could try to do some layer re-ordering, but you might be foiled by UIImageView's own internal code. My suggestion would be be to create a container view and add your sublayers there, then add the image view as a subview (which is essentially adding it as a sublayer as well). As long as the image has transparency and the UIImageView is not opaque, it will work.
This code worked for me in a playground:
let container = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let imageView = UIImageView(frame: container.bounds)
imageView.image = UIImage(named: "duck.png")
imageView.isOpaque = false
let shape = CAShapeLayer()
shape.path = UIBezierPath(roundedRect: container.bounds, cornerRadius: 2).cgPath
shape.strokeColor = UIColor.black.cgColor
shape.lineWidth = 10
shape.fillColor = UIColor.blue.cgColor
shape.borderColor = UIColor.black.cgColor
container.layer.addSublayer(shape)
container.addSubview(imageView)
Good luck!

UIImage appears differently in UIImageView than it does when saved to disk

I'm having a problem where a UIImage that I build in a playground appears correctly when I inspect it in a UIImageView within the playground...
...but incorrectly when I save it to disk.
Here is the code I'm using to build/inspect/save the UIImage:
import UIKit
import XCPlayground
// Size of view and layers
let size = CGSize(width: 180, height: 180)
// Create a layer
let layer = CALayer()
layer.frame = CGRect(origin: CGPointZero, size: size)
layer.backgroundColor = UIColor.blackColor().CGColor
// And a sublayer
let sublayer = CALayer()
sublayer.frame = CGRect(origin: CGPointZero, size: size)
sublayer.cornerRadius = 180
sublayer.backgroundColor = UIColor.whiteColor().CGColor
layer.addSublayer(sublayer)
// Render the layer into an image
UIGraphicsBeginImageContext(size)
layer.renderInContext(UIGraphicsGetCurrentContext())
let im = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// Inspect the image within the playground
let view = UIImageView(image: im)
XCPShowView("Container View", view: view)
view.layer.addSublayer(layer)
// Save the image to disk
let data = NSData(data: UIImagePNGRepresentation(im)!)
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var docs: String = paths[0] as String
let fullPath = docs.stringByAppendingPathComponent("icon.png")
let result = data.writeToFile(fullPath, atomically: true)
How can I render the image to disk to reflect what I see in the UIImageView?
The petal shaped thing is what I expect to see if the radius is larger than what makes a circle. If you click the "Show result" icon in playground next to the let view = UIImageView(image: im) line, it will show your image the exact same way as it is stored on disk. See below. I changed the colors while experimenting with it, but otherwise it is your code...
So I think that what is shown in XCPShowView("Container View", view: view) is incorrect, not the other way around.