Miałem ten sam problem. Dziękuję wszystkim, którzy odpowiedzieli - udało mi się wspólnie znaleźć rozwiązanie, korzystając z części kilku z tych odpowiedzi.
Moim rozwiązaniem jest użycie Swift 5
Problem, który próbujemy rozwiązać, polega na tym, że możemy mieć obrazy o różnych proporcjach w naszych obrazach, TableViewCell
ale chcemy, aby były renderowane ze stałą szerokością. Obrazy powinny oczywiście renderować się bez zniekształceń i wypełniać całą przestrzeń. W moim przypadku nie przeszkadzało mi trochę „przycinanie” wysokich, chudych obrazów, więc użyłem trybu treści.scaleAspectFill
Aby to zrobić, utworzyłem niestandardową podklasę UITableViewCell
. W moim przypadku nazwałem to StoryTableViewCell
. Cała klasa jest wklejona poniżej, z komentarzami w tekście.
To podejście zadziałało, gdy korzystałem również z niestandardowego widoku akcesoriów i długich etykiet tekstowych. Oto obraz wyniku końcowego:
Renderowany widok tabeli ze stałą szerokością obrazu
class StoryTableViewCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
// ==== Step 1 ====
// ensure we have an image
guard let imageView = self.imageView else {return}
// create a variable for the desired image width
let desiredWidth:CGFloat = 70;
// get the width of the image currently rendered in the cell
let currentImageWidth = imageView.frame.size.width;
// grab the width of the entire cell's contents, to be used later
let contentWidth = self.contentView.bounds.width
// ==== Step 2 ====
// only update the image's width if the current image width isn't what we want it to be
if (currentImageWidth != desiredWidth) {
//calculate the difference in width
let widthDifference = currentImageWidth - desiredWidth;
// ==== Step 3 ====
// Update the image's frame,
// maintaining it's original x and y values, but with a new width
self.imageView?.frame = CGRect(imageView.frame.origin.x,
imageView.frame.origin.y,
desiredWidth,
imageView.frame.size.height);
// ==== Step 4 ====
// If there is a texst label, we want to move it's x position to
// ensure it isn't overlapping with the image, and that it has proper spacing with the image
if let textLabel = self.textLabel
{
let originalFrame = self.textLabel?.frame
// the new X position for the label is just the original position,
// minus the difference in the image's width
let newX = textLabel.frame.origin.x - widthDifference
self.textLabel?.frame = CGRect(newX,
textLabel.frame.origin.y,
contentWidth - newX,
textLabel.frame.size.height);
print("textLabel info: Original =\(originalFrame!)", "updated=\(self.textLabel!.frame)")
}
// ==== Step 4 ====
// If there is a detail text label, do the same as step 3
if let detailTextLabel = self.detailTextLabel {
let originalFrame = self.detailTextLabel?.frame
let newX = detailTextLabel.frame.origin.x-widthDifference
self.detailTextLabel?.frame = CGRect(x: newX,
y: detailTextLabel.frame.origin.y,
width: contentWidth - newX,
height: detailTextLabel.frame.size.height);
print("detailLabel info: Original =\(originalFrame!)", "updated=\(self.detailTextLabel!.frame)")
}
// ==== Step 5 ====
// Set the image's content modoe to scaleAspectFill so it takes up the entire view, but doesn't get distorted
self.imageView?.contentMode = .scaleAspectFill;
}
}
}
self.imageView.bounds
obraz zostanie wyśrodkowany.