所以我试图做类似于Instagram的视图,这应该相当简单。仅开始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
}
}
和
{{1}}
我的理论是,图像比手机中可用的尺寸大,并且具有“适合度”,它只是在图像的上方和下方增加了一些透明度。
我该如何解决这个问题?
答案 0 :(得分:2)
您似乎是让图像视图的大小由图像视图的内在大小决定。但无论图像视图的内容模式如何,图像视图的固有大小都由图像大小决定。
您可以为图像视图的大小定义约束,而不是依赖于图像视图的固有大小,例如:
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
返回时执行即时调整约束,则单元格将生成有关表格单元格内在高度的各种自动布局警告(均匀如果约束实际上是完全可满足的。)
其次,如果您的单元格的高度可以根据外部输入(例如图像的大小)而改变,那么您经常需要约束单元格中图像视图的高度,恕我直言。如果你让细胞中的图像变得荒谬的高度(如果图像是一张200像素宽和2000像素高的胡萝卜的垂直照片,那么你最终可能会遇到奇怪的用户体验,其中图像视图太高而你输了整个"我在桌面视图中滚动"的氛围。
所以我喜欢约束图像视图的最大高度,无论图像如何。所以,在IB中,我定义了一个约束,它表示图像视图的高度应该是<=
到200点(使用你想要的任何值)。然后我使用内容模式来显示&#34;缩放方面适合&#34;。
请注意,除了上述内容之外,另一种方法是保留您的约束,但是调整图像本身的大小,这样如果它非常大,那么它会缩小到适合于图像视图的宽度。例如,您可以执行以下操作:
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)
}
}
这&#34;调整图像大小&#34;方法有另一个优点。小图像视图中的大图像仍然需要大量内存。但是,如果您将图像调整为适合图像视图的大小,则可以避免浪费内存。