Change the size of UIImageView in a UITableViewCell - ios

I am a newbie in Swift And Xcode.
Is there any clean way to change UIImageView Size placed inside a UITableViewCell?
This is my TableView, I want to align left label correctly

Replace
cell.imageView!.image = image
with
cell.imageView?.image = image.scaleImage(toSize: CGSize(width: 40, height: 40))
Add this UIImageView extension to the project.
extension UIImage {
func scaleImage(toSize newSize: CGSize) -> UIImage? {
var newImage: UIImage?
let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
if let context = UIGraphicsGetCurrentContext(), let cgImage = self.cgImage {
context.interpolationQuality = .high
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height)
context.concatenate(flipVertical)
context.draw(cgImage, in: newRect)
if let img = context.makeImage() {
newImage = UIImage(cgImage: img)
}
UIGraphicsEndImageContext()
}
return newImage
}
}
Reason for the error in your code is UITableViewCell is assigning the various size for UIImageView based on the image size inside it. In addition to I've adjusted the image to specific size so that it can fit to imageView content in UITableViewCell.
Note:
Please don't post the screenshots of the code as it does not help to others to copy it from the question and which attracts -ve voting as well. However, you can post the screenshots for XIBs, Storyboards and for Simulation errors.

You could use a stack view or a view with proportianal constraint to the relavite view in your cell xib. In this way the portion of the flag will be always the same.
Otherwise, if you want to do it quickly, you can contraint the leading of the label to the cell view and not with the flag. It's a litte bit dirtier but it should work.

Fix the width of the UIImageView and set its contentMode to .scaleAspectFit.
myImageView.safeAreaLayoutGuide.widthAnchor.constraint(equalToConstant: 50).isActive = true
myImageView.contentMode = .scaleAspectFit
myImageView.clipsToBounds = true
However, if you are using the storyboard, you can set these properties there itself.

Related

Image isn't bound to the UIImageView

I have a UIImageView in created in Inspector that I resize in my code based on a selected image which i get from the web. However on first load of the image, it's being displayed in the images normal resolution instead of the UIImageViews newly created bounds.
Resizing the UIImageView:
fullScreenImage.bounds.size = CGSize(width: scaledWidth, height: scaledHeight)
Setting the UIImageView's image
let imageStringURL = images[indexPath.row].urls!["regular"]
let imageURL = URL(string: imageStringURL!)!
let imageData = try! Data(contentsOf: imageURL)
let image = UIImage(data: imageData)
fullScreenImage.image = image
This is how it looks when the image is first clicked on to enter "fullscreen mode"
This is how it looks the second time i click it
Not really sure why the Image isn't bounding itself within the specified UIImageView bounds
Instead of resizing the bound, you can set the UIViewContentMode property of UIImageView. This will resize the imageView image to fit inside the bounds.
fullScreenImage.contentMode = .scaleAspectFit
I found a workaround solution. I tried setting the contentMode to aspect fit, and i also tried enabling clip to bounds in the inspector, however none of them worked. So I simply looked into just resizing the UIImage itself and placing it into the UIImageView.
I found an extension in another post for a UIImage that resizes it
extension UIImage{
func resizeImage(newSize: CGSize) -> UIImage {
// Guard newSize is different
guard self.size != newSize else { return self }
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
}
If anyone knows of a better way please let me know :)

Adding UIImage ignores and resizes UIImageView frame

I'm currently trying to add an image into the navigation item for one view. In the view's viewDidLoad(), a function is called with the following code, similar to this post:
let logo = UIImage(named: "Menu_Logo")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 122, height: 26))
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.image = logo
self.navigationItem.titleView = imageView
Instead of giving me the expected size however, the view ends up looking like this:
Removing the UIImage from the UIImageView makes the view sized correctly like this:
This seems like strange behaviour to me, especially since I did set the content mode to .scaleAspectFit. Is there something I am forgetting regarding adding an UIImageView as the navigationItem.titleView?
On UINavigationBar, title view takes its full size, if content is large.
Resize the image rather than UIImageView as following with passing size (122, 26). This will solve your problem.
func imageResize(sizeChange: CGSize) -> UIImage {
let hasAlpha = true
let scale: CGFloat = 0.0 // Use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(sizeChange, !hasAlpha, scale)
self.draw(in: CGRect(origin: CGPoint.zero, size: sizeChange))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
return scaledImage!
}

creating circular pics for tableview cell images

I'm trying to make images circular in a tableview cell, I've the various ways I've seen on stackoverflow but this is the closest I've gotten:
As you can see they look more like elipses than circles. In storyboard I have the constraints set to keeping the aspect ratio 1:1 and the view mode "aspect fill". I'm using this UIImage extension for the circular shape:
extension UIImage {
var circleMask: UIImage {
let square = CGSize(width: min(size.width, size.height), height: min(size.width, size.height))
let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
imageView.contentMode = UIViewContentMode.scaleAspectFill
imageView.image = self
imageView.layer.cornerRadius = square.width/2
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 5
imageView.layer.masksToBounds = true
UIGraphicsBeginImageContext(imageView.bounds.size)
imageView.layer.render(in: UIGraphicsGetCurrentContext()!)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
}
This is how my cellForRowAt IndexPath looks:
let cell = detailTableView.dequeueReusableCell(withIdentifier: castResuseIdentifier)
as! CastCell
let cast = castArray[indexPath.row]
cell.actorName.text = cast.name
cell.characterName.text = cast.character
cell.actorProfileImage.image = castImageArray[indexPath.row].circleMask
self.detailTableView.rowHeight = 100
detailTableView.allowsSelection = true
return cell
Not sure why they aren't perfect circles, any idea?
That is a really non-performant way of achieving that effect, since you're creating a UIImageView and rendering it to a separate image context every time.
For a quick and easy way to do it, just set the cornerRadius property for the layer of the actorProfileImage view inside your CastCell.
By not using the extension and instead adding this to the cellForRowAtIndexPath the images came out circular
cell.actorProfileImage.layer.cornerRadius = cell.actorProfileImage.frame.size.height/2
cell.actorProfileImage.clipsToBounds = true
cell.actorProfileImage.layer.masksToBounds = true

How to tint an animated UIImageView?

I'm attempting to apply tint of a UIImageView consisting of programatically loaded animationImages. Currently using iOS 9.3.
I think I've tried every proposed solution found here for applying the tint including:
Setting the .renderMode on load with: let newImage: UIImage? =
UIImage(named: filename as
String)!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
Setting the tintView either in the Storyboard or programatically
with: zeroImageView.tintColor = UIColor.redColor()
Setting the image .renderMode through the UIImageView itself:
zeroImageView.image = zeroImageView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
Setting the UIImageView's renderMode through the Interface Builder
user defined runtime attributes: imageRenderingMode Number 2
The image sequence is of PNGs with transparency, so, I would like to re-colour the image and maintain the transparency.
I've had no luck and am sort of at a loss. Wondering if maybe these methods only work for a still UIAnimationView? Any help would be greatly appreciated, thanks!
Here's some code:
// Load all images
while let element = enumerator.nextObject() as? String {
if element.hasSuffix("png") {
let filename: NSString = "Digits/0/" + element
print(filename)
imageNames.append(filename as String)
let newImage: UIImage? = UIImage(named: filename as String)!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
images.append(newImage!)
zeroImageView.tintColor = UIColor.redColor()
}
}
// Make animated UIImageView
zeroImageView.userInteractionEnabled = false
zeroImageView.animationImages = images
zeroImageView.animationDuration = 2.0
zeroImageView.startAnimating()
zeroImageView.tintColor = UIColor.redColor()
Try this...
extension UIImage {
func image(withTint tint: UIColor) -> UIImage? {
guard let cgImage = cgImage else {
return nil
}
UIGraphicsBeginImageContextWithOptions(size, false, scale)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}
let rect = CGRect(origin: .zero, size: size)
context.translateBy(x: 0, y: size.height)
context.scaleBy(x: 1.0, y: -1.0)
context.setBlendMode(.normal)
context.clip(to: rect, mask: cgImage)
tint.setFill()
context.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}
If none of those worked the next step I would do is programmatically place an empty UIView on top of the UIImageView. First off, it would not interfere with anything going on in the UIImageView.
I would check out this tutorial here: http://www.apptuitions.com/programmatically-creating-uiview-uislider-uiswitch-using-swift/
this will teach you how to programmatically add a UIView to the storyboard. I would add this code in the viewDidLoad() method.
The main thing you need to change is the background color of the UIView. First you have to decide what the color of the tint (which from what I see in your code is red) and then explicitly change the 'Alpha' of the color so that it is barely showing. You change the 'Alpha' because that is basically the opacity of the color.
Hope this helps.

Swift / cut background image

My background image is set with UIView extension.
extension UIView {
func addBackground() {
// screen width and height:
let width = UIScreen.mainScreen().bounds.size.width
let height = UIScreen.mainScreen().bounds.size.height
let imageViewBackground = UIImageView(frame: CGRectMake(0, 0, width, height))
imageViewBackground.image = UIImage(named: "index_clear")
// you can change the content mode:
imageViewBackground.contentMode = UIViewContentMode.ScaleAspectFill
self.addSubview(imageViewBackground)
self.sendSubviewToBack(imageViewBackground)
}}
For segue animation the view moves from left to right. The background image is way larger than the screen, what is visible while the animation.
How can I cut the background image to perfectly fit into the view?
.ScaleAspectFit does the job, but since it's a picture it looks bad.
Help is very appreciated.
You can use .ScaleAspectFill to crop the image rather than scale it to fit. This won't distort your image, but obviously you won't be able to see the whole thing.
You need to ensure that you set clipsToBounds=true on the UIImageView so that the cropped area isn't visible
extension UIView {
func addBackground() {
// screen width and height:
let width = UIScreen.mainScreen().bounds.size.width
let height = UIScreen.mainScreen().bounds.size.height
let imageViewBackground = UIImageView(frame: CGRectMake(0, 0, width, height))
imageViewBackground.image = UIImage(named: "index_clear")
// you can change the content mode:
imageViewBackground.contentMode = UIViewContentMode.ScaleAspectFill
imageViewBackground.clipsToBounds=true
self.addSubview(imageViewBackground)
self.sendSubviewToBack(imageViewBackground)
}

Resources