Xcode Imageview Aspect Fit Remove Extra Space

佐手、 提交于 2019-11-28 12:18:44

I had the same issue. This happens when the original image size is larger (in width and/or height) than the UIImageView that holds it and the image is resized with Aspect Fit to fit into the UIImageView.

Here, the image width is larger than can fit into the UIImageView so Aspect Fit resizes the image, keeping the original aspect ratio. If you read the image size (via watch or breakpoint or something) you will see that the image size is (for example) 600(h) x 800(w) (3:4 ratio). The UIImageView width is (e.g.) 320(w) thus the displayed image is scaled to 240(h) x 320(w) (keeping the 3:4 ratio). BUT the image width is still REALLY 600 x 800 and as there is no limitation on the UIImageView height the UIImageView size is 600 x 320 --> it sets the UIImageView height to the original image height (600) because it can.

My solution is this: (Swift 3)

Add a height constraint to the UIImageView in Main.storyboard and link it through an Outlet:

@IBOutlet weak var displayimage: UIImageView!
@IBOutlet weak var displayimageHeightConstraint: NSLayoutConstraint!

Then test whether the UIImageView is smaller (width) than the image it holds. If so, set the height constraint so that the UIImageView height:width ratio is the same as the image aspect ratio:

if displayimage.frame.size.width < (displayimage.image?.size.width)! {
    displayimageHeightConstraint.constant = displayimage.frame.size.width / (displayimage.image?.size.width)! * (displayimage.image?.size.height)!
}

The complementary operation is also possible if there is whitespace at the sides of the image due to an issue of resizing where the UIImageView height is limited and the width is set to the original image width.

@IBOutlet weak var displayimageWidthConstraint: NSLayoutConstraint!

if displayimage.frame.size.height < (displayimage.image?.size.height)! {
    displayimageWidthConstraint.constant = displayimage.frame.size.height / (displayimage.image?.size.height)! * (displayimage.image?.size.height)!
}

The above answer doesn't work when using UITableViewAutomaticDimension.

In general the problem is that in the tableView function "cellForRowAt indexPath" tableView hasn't yet laid out cell and it's subviews.

So one solution to this problem is using a subclass of UITableView:

class MyUITableView: UITableView {

    // Makes real device cell width available in "cellForRowAt indexPath"
    override func dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCell {
        let cell = super.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
        cell.frame.size.width = self.frame.size.width
        cell.layoutIfNeeded()
        return cell
    }
}

Now you can use any of the solutions in for instance the link in Md Rais' comment. As an example my own code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ViewCell

    if let attach = eventsByDay[indexPath.section][indexPath.row].attachPhoto {
        let cellWidth = cell.attachPhoto.frame.size.width
        let scale = cellWidth / attach.size.width
        let size = CGSize(width: cellWidth, height: attach.size.height * scale)

        UIGraphicsBeginImageContextWithOptions(size, true, 0.0)             
        attach.draw(in: CGRect(origin: CGPoint.zero, size: size))
        cell.attachPhoto.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    } else {
        cell.attachPhoto.image = nil
    }

    // ...
    return cell
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!