I'm a beginner with swift and I can't get the resize of a UIImageView working.
Here is my current layout :
What I want is to resize the images to occupy half the screen's width (2 images per row).
Here is my storyboard :
Here is the function drawing the collection view inside my controller :
func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
var cell : MenuInspirationCellView = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as MenuInspirationCellView
cell.imageView.layer.borderWidth = 2
cell.imageView.layer.borderColor = UIColor.yellowColor().CGColor
//This is my first approach trying to modify the frame :
cell.imageView.frame = CGRectMake(0,0, self.view.bounds.width / 2,v120)
var cellImage : UIImage = UIImage(data: NSData(contentsOfURL: NSURL(string: images[indexPath.row])))
cell.imageView.image = cellImage;
//This is my second approach (based on http://www.snip2code.com/Snippet/89236/Resize-Image-in-iOS-Swift) :
// to resize an image to dimension 52x52
//var newSize:CGSize = CGSize(width: 52,height: 52)
//let rect = CGRectMake(0,0, newSize.width, newSize.height)
//UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
// image is a variable of type UIImage
//cellImage.drawInRect(rect)
//let newImage = UIGraphicsGetImageFromCurrentImageContext()
//UIGraphicsEndImageContext()
// resized image is stored in constant newImage
//cell.imageView.image = newImage;
//This is my thrid approach (based on https://gist.github.com/hcatlin/180e81cd961573e3c54d, of course i added his functions but I don't show them here for the sake of readability) :
//cell.imageView.image = self.RBSquareImageTo(cellImage, size: CGSize(width: 80, height: 80))
return cell
}
Any leads to sort this out ?
SWIFT:
func imageResize(imageObj:UIImage, sizeChange:CGSize)-> UIImage {
let hasAlpha = false
let scale: CGFloat = 0.0 // Automatically use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(sizeChange, !hasAlpha, scale)
imageObj.drawInRect(CGRect(origin: CGPointZero, size: sizeChange))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext() // !!!
return scaledImage
}
The sizes of your cells are decided by your UICollectionViewLayout object, which is a UICollectionViewFlowLayout in your case. If you want all of your cells to be the same size, you can configure the properties on the layout itself; itemSize and minimumInterimSpacing will do the trick. Alternatively, if you want your cells to be different sizes, say depending on the image each contains or whatever, you needs your collection view delegate to implement the UICollectionViewDelegateFlowLayout method:
optional func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize
returning the size you want for each cell.
Following this tutorials you can resize UIImage, In that tutorial described fully .. Image Resize in swift ios8
func imageResize (imageObj:UIImage, sizeChange:CGSize)-> UIImage{
let hasAlpha = false
let scale: CGFloat = 0.0 // Automatically use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(sizeChange, !hasAlpha, scale)
imageObj.drawInRect(CGRect(origin: CGPointZero, size: sizeChange))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
return scaledImage
}
Here you can also see many tutorials about Swift language Visit Here iPhone & iPad Application Development Help World
Related
What I want to achive is something like list view in Files App. Document will display a little thumbnail if has one. Otherwise a SF Symbol with textStyle .callout will show up. All the rows’ labels should be left aligned. But currently the thumbnails are much bigger than the SF Symbols so that they push the labels away.
I emphasize textStyle because my app supports dynamic type, which means the imageView's frame calculation should base on SF Symbol.
I try to override layoutSubviews. But can't figure out how to do the calculation.
Files App
My App
For maximum control of your cell appearance, you should create a custom cell. But, if you want use a standard Subtitle cell, you can resize your images when setting them.
There are some excellent image scaling functions in this Stack Overflow answer: how to resize a bitmap on iOS
Add the extensions from that answer to your project. Specifically, for your needs, we'll use scaledAspectFit().
So, assuming you have a Subtitle cell prototype, with identifier of "cell", your cellForRowAt will look something like this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// however you have your data stored
let title = "IMG_0001.JPG"
let subtitle = "Today at 10:15 AM, 2.5 MB"
let imgName = "IMG_0001"
cell.textLabel?.text = title
cell.detailTextLabel?.text = subtitle
if let img = UIImage(named: imgName) {
// default cell image size is 56x56 (points)
// so we'll proportionally scale the image,
// using screen scale to get the best resolution
let widthHeight = UIScreen.main.scale * 56
let scaledImg = img.scaledAspectFit(to: CGSize(width: widthHeight, height: widthHeight))
cell.imageView?.image = scaledImg
}
return cell
}
Edit
Takes only a little research to implement the use fo SF Symbols...
Add this func to your table view controller - it will return a UIImage of an SF Symbol at specified point size, centered in specified size:
private func drawSystemImage(_ sysName: String, at pointSize: CGFloat, centeredIn size: CGSize) -> UIImage? {
let cfg = UIImage.SymbolConfiguration(pointSize: pointSize)
guard let img = UIImage(systemName: sysName, withConfiguration: cfg) else { return nil }
let x = (size.width - img.size.width) * 0.5
let y = (size.height - img.size.height) * 0.5
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { context in
img.draw(in: CGRect(origin: CGPoint(x: x, y: y), size: img.size))
}
}
Then change your cellForRowAt func as needed:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// however you have your data stored
let title = "IMG_0001.JPG"
let subtitle = "Today at 10:15 AM, 2.5 MB"
let imgName = "IMG_0001"
cell.textLabel?.text = title
cell.detailTextLabel?.text = subtitle
// defalt image view size
let wh = UIScreen.main.scale * 56
let targetSize = CGSize(width: wh, height: wh)
// for this example, if it's the first row, generate an image from SF Symbol
if indexPath.row == 0 {
if let img = drawSystemImage("doc.text", at: UIScreen.main.scale * 24, centeredIn: targetSize) {
cell.imageView?.image = img
}
} else {
if let img = UIImage(named: imgName) {
// default cell image size is 56x56 (points)
// so we'll proportionally scale the image,
// using screen scale to get the best resolution
let scaledImg = img.scaledAspectFit(to: targetSize)
cell.imageView?.image = scaledImg
}
}
return cell
}
I'll leave it up to you to tweak the point size as desired (and configure any other properties of your SF Symbol image such as weight, scale, color, etc).
I'm getting a second long delay when selecting my collectionview cell. Here is my current code for collection view did select:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let vc = PopUpCellViewController(nibName: "PopUpCellViewController", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)
print("called")
let cell = collectionView.cellForItem(at: indexPath) as! AnnotatedPhotoCell
sourceCell = cell
vc.picture = resizeImage(image: cell.imageView.image!, targetSize: CGSize(width: (view.bounds.width - 45),height: 0))
vc.comment = cell.commentLabel
var image = UIImage(named: "back_button_thick")
image = image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
self.navigationController?.navigationBar.backIndicatorImage = image
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = image
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
}
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
let size = image.size
let widthRatio = targetSize.width / image.size.width
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
I am using a UIViewControllerAnimatedTransitioning. I am confident that there is no delay with my UIViewControllerAnimatedTransitioning. There seems to be an issue with my CollectionView Did select function. If switch my code in my didSelect function for a print statement, there is no longera delay.
I have two solutions:
1: PROBABLY NOT: I'm guessing that it's giving an annoying delay because it's taking a while for your app to run the code to get the nib file, and change all those things while it shouldn't.
2: PROBABLY: Perhaps running it on a real device will help. Xcode always has bugs, so don't worry. :)
I'm using Swift 3.0 with Xcode 8 and I'm having some problems with image resizing. Here is the code where i set my UIImage frame.
open func setData(_ data: Any?, image: String) {
self.textLabel?.font = UIFont.boldSystemFont(ofSize: 10)
self.textLabel?.textColor = UIColor(hex: "000000")
if let menuText = data as? String {
self.textLabel?.text = menuText
}
self.imageView?.contentMode = UIViewContentMode.scaleToFill
self.imageView?.frame = CGRect(x: 12, y: 8, width: 10, height: 10)
self.imageView?.image = UIImage(named: image)
self.imageView?.clipsToBounds = true
}
And here is where I call my function inside my tableView. I don't have any problem with setting the image, but ONLY with resize. When i use smaller images, the image is smaller, when i use bigger images, the image gets bigger, it doesnt resize.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = BaseTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: BaseTableViewCell.identifier)
cell.setData(menus[indexPath.row], image: images[indexPath.row])
return cell
}
I have solved it by using this resize function to resize my image and then place in the ImageView
func imageResize(image:UIImage,imageSize:CGSize)->UIImage
{
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0.0)
[image .draw(in: CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))]
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext()
return newImage!
}
If you are using default image view of uitableview cell than you won't be able to resize it. Some default constraints are already there.
You have two options :
create a subclass of uitableview cell and use your own image view (don't create the outlet with name imageView, try something else).
Resize the image using https://stackoverflow.com/a/45100626/5383852
I need to have a screenshot of a specific UITableView row and remove/add content to the cell before the screenshot.
For example: the cell contains only a text and a share button. On share button click, I want the app to generate an image with the text and my app logo on the top (without the share button).
What is the best approach to do this? and how?
Thanks in advance.
#Nirav already gave you a hint in the comment section with this post:
How to take screenshot of portion of UIView?
So, you have now to get the Rect of the cell in the superview, so i made a sample action method:
#IBOutlet var snapImageView: UIImageView!
#IBAction func snapshotrow(_ sender: Any) {
//get the cell
if let cell = myTable.cellForRow(at: IndexPath(row: 0, section: 0)) as? MyCustomCellClass {
//hide button
cell.shareButton.isHidden = true
let rectOfCellInTableView = myTable.rectForRow(at: IndexPath(row: 0, section: 0))
let rectOfCellInSuperview = myTable.convert(rectOfCellInTableView, to: myTable.superview)
snapImageView.image = self.view.snapshot(of: rectOfCellInSuperview)
let finalImage = saveImage(rowImage: snapImageView.image)
//test final image
snapViewImage.image = finalImage
}
}
func saveImage(rowImage: UIImage) -> UIImage {
let bottomImage = rowImage
let topImage = UIImage(named: "myLogo")!
let newSize = CGSize.init(width: 41, height: 41) // set this to what you need
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
bottomImage.draw(in: CGRect(origin: .zero, size: newSize))
topImage.draw(in: CGRect(origin: .zero, size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
and I was able to get the snapshot of the 0th cell of my table view and assigned it to the snapImageView.
Now the last step is to save the image to the camera roll, there are lots of related post out there in SO.
Source: Get Cell position in UITableview
Adding logo and hiding share button: Saving an image on top of another image in Swift
I am creating an application that Holds about 26 images inside of a structure, and then I load those images into a table view, and anytime a new image comes into the View of the simulator, there is a bit of lag. It is definitely a problem dealing with loading images inside of the Table View.
I think I need to add an async, but I have no idea how to do that. If someone could guide me in the right direction on what I should do to achieve smooth scrolling, that would be awesome!
I wish I could post a photo, but I don't have a good enough reputation on StackOverFlow.com.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var question : Question
question = Questions[indexPath.row]
var titleLabel = cell.contentView.viewWithTag(1) as UILabel
titleLabel.text = question.name
var backgroundImage = cell.contentView.viewWithTag(5) as UIImageView
backgroundImage.image = UIImage(named: question.pic)
var frame : CGRect = CGRectMake(0, backgroundImage.frame.size.height - 200, backgroundImage.frame.size.width, backgroundImage.frame.size.height - 200)
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.mainScreen().scale
return cell
}
It has to do with the size of the images. Use a smaller thumbnails for the tableView cells. Convert your images smaller for it.
CGSize destinationSize = CGSizeMake(160, 160);
UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Kreuzberg's answer solved my problem, as I was getting jerky performance even with GCD and main_queue implemented. Since I can't add too much code in comments, I expanded on his answer so the width/height could be a bit more dynamic.
if (image.size.width > MAX_THUMBNAIL_RESOLUTION || image.size.height > MAX_THUMBNAIL_RESOLUTION) {
int width;
int height;
CGFloat ratio = image.size.width/image.size.height;
if (ratio > 1) {
width = MAX_THUMBNAIL_RESOLUTION;
height = width / ratio;
}
else {
height = MAX_THUMBNAIL_RESOLUTION;
width = height * ratio;
}
CGSize destinationSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext(destinationSize);
[image drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
You can make the constant MAX_THUMBNAIL_RESOLUTION to be anything you think reasonable. Or, you can calculate screen density and use a multiplier.