- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
所以我正在尝试做类似 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
}
}
我的理论是图像比在手机中可用的尺寸大得多,并且具有“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/
我是一名优秀的程序员,十分优秀!