gpt4 book ai didi

ios - 具有动态大小和纵横比的 UIImages。我究竟做错了什么?

转载 作者:搜寻专家 更新时间:2023-11-01 06:33:44 25 4
gpt4 key购买 nike

所以我正在尝试做类似 instagram 的 View ,这应该相当简单。仅启动一个 UITableViewController 和一个仅包含标签和图像的 UITableViewCell:

class FoodListVC: UITableViewController {

let samples = [
"things",
"stuff",
"foo"
]
let images = [
UIImage(named: "photo1"),
UIImage(named: "photo2"),
UIImage(named: "photo3")
]

override func viewDidLoad() {
super.viewDidLoad()

// Row size
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 88
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return samples.count
}

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

cell.setContent(title: samples[indexPath.row], image: images[indexPath.row]!)

return cell
}
}

和:

class FoodCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var mainImage: UIImageView!

override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

func setContent(title: String, image: UIImage) {
titleLabel.text = title

mainImage.image = image
mainImage.backgroundColor = UIColor.red
}

}

在界面布局中,事情看起来也很简单: enter image description here

但是,一旦我加载应用程序,边距就非常大:enter image description here

我的理论是图像比在手机中可用的尺寸大得多,并且具有“Aspect Fit”,它只是在图像上方和下方增加了一些透明度。

我该如何解决这个问题?

最佳答案

您似乎让 ImageView 的大小由 ImageView 的固有大小决定。但是 ImageView 的固有大小由图像的大小决定,与 ImageView 的内容模式无关。

您可以为 ImageView 的大小定义一个约束,而不是依赖于 ImageView 的固有大小,例如:

class FoodCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var mainImage: UIImageView!

private var aspectConstraint: NSLayoutConstraint?

func setContent(title: String, image: UIImage) {

// remove constraint, if any

if aspectConstraint != nil {
mainImage.removeConstraint(aspectConstraint!)
}

// add constraint

let ratio = image.size.width / image.size.height
aspectConstraint = NSLayoutConstraint(item: mainImage, attribute: .width, relatedBy: .equal, toItem: mainImage, attribute: .height, multiplier: ratio, constant: 0)
aspectConstraint?.priority = 999
mainImage.addConstraint(aspectConstraint!)

// set the image and label

titleLabel.text = title
mainImage.image = image
mainImage.backgroundColor = .red
}

}

请注意,我将其设置为高优先级约束,但小于 1000。我这样做有两个原因:

  • 首先,如果您在从 cellForRowAt 返回时对约束进行即时调整,单元格将生成关于表格 View 单元格固有高度的各种自动布局警告。 (即使约束实际上是完全可满足的)。

  • 其次,恕我直言,当您的单元格的高度可以根据外部输入(例如图像的大小)发生变化时,您通常希望限制单元格中 ImageView 的高度。如果让单元格中的图像增长到荒谬的高度(如果图像是 200 像素宽和 2000 像素高的胡萝卜的垂直照片怎么办),您最终可能会得到奇怪的用户体验,其中 ImageView 太高以至于您丢失整个“我在表格 View 中滚动”的氛围。

    所以我喜欢限制 ImageView 的最大高度,而不考虑图像。因此,在 IB 中,我定义了一个约束条件,表示 ImageView 的高度应为 <=。到 200 点(使用您想要的任何值)。然后,我为“缩放方面适合”的图像使用内容模式。


请注意,除上述方法外,另一种方法是保持约束不变,但调整图像本身的大小,以便如果它真的很大,则将其缩小到适合图像宽度的大小看法。例如,您可以执行以下操作:

func setContent(title: String, image: UIImage) {
titleLabel.text = title

if image.size.width > mainImage.frame.width {
let size = CGSize(width: mainImage.frame.width, height: max(200, mainImage.frame.width * image.size.height / image.size.width))
mainImage.image = image.scaledAspectFit(to: size)
} else {
mainImage.image = image
}

mainImage.backgroundColor = .red
}

地点:

extension UIImage {

/// Resize the image to be the required size, stretching it as needed.
///
/// - parameter newSize: The new size of the image.
/// - parameter contentMode: The `UIViewContentMode` to be applied when resizing image.
/// Either `.scaleToFill`, `.scaleAspectFill`, or `.scaleAspectFit`.
///
/// - returns: Return `UIImage` of resized image.

func scaled(to newSize: CGSize, contentMode: UIViewContentMode = .scaleToFill) -> UIImage? {
if contentMode == .scaleToFill {
return filled(to: newSize)
} else if contentMode == .scaleAspectFill || contentMode == .scaleAspectFit {
let horizontalRatio = size.width / newSize.width
let verticalRatio = size.height / newSize.height

let ratio: CGFloat!
if contentMode == .scaleAspectFill {
ratio = min(horizontalRatio, verticalRatio)
} else {
ratio = max(horizontalRatio, verticalRatio)
}

let sizeForAspectScale = CGSize(width: size.width / ratio, height: size.height / ratio)
let image = filled(to: sizeForAspectScale)
if contentMode == .scaleAspectFill {
let subRect = CGRect(
x: floor((sizeForAspectScale.width - newSize.width) / 2.0),
y: floor((sizeForAspectScale.height - newSize.height) / 2.0),
width: newSize.width,
height: newSize.height)
return image?.cropped(to: subRect)
}
return image
}
return nil
}

/// Resize the image to be the required size, stretching it as needed.
///
/// - parameter newSize: The new size of the image.
///
/// - returns: Resized `UIImage` of resized image.

func filled(to newSize: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(newSize, false, scale)
draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return image
}

/// Crop the image to be the required size.
///
/// - parameter bounds: The bounds to which the new image should be cropped.
///
/// - returns: Cropped `UIImage`.

func cropped(to bounds: CGRect) -> UIImage? {
var rect = bounds
rect.size.width *= scale
rect.size.height *= scale

if let imageRef = cgImage?.cropping(to: rect) {
return UIImage(cgImage: imageRef, scale: scale, orientation: imageOrientation)
} else {
return nil
}
}

/// Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed.
///
/// - parameter newSize: The new size of the image.
///
/// - returns: Return `UIImage` of resized image.

func scaledAspectFill(to newSize: CGSize) -> UIImage? {
return scaled(to: newSize, contentMode: .scaleAspectFill);
}

/// Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place.
///
/// - parameter newSize: The new size of the image.
///
/// - returns: Return `UIImage` of resized image.

func scaledAspectFit(to newSize: CGSize) -> UIImage? {
return scaled(to: newSize, contentMode: .scaleAspectFit)
}

}

这种“调整图像大小”的方法还有另一个优点。小 ImageView 中的大图像仍然需要大量内存。但是,如果您将图像调整为适合 ImageView 的大小,则可以避免浪费内存。

关于ios - 具有动态大小和纵横比的 UIImages。我究竟做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44169594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com