[英]Keep aspect ratio of an UIImageView in a custom UITableViewCell
所以我想做的是让我的自定义UITableViewCell
包含一个UIImageView
其中包含一个图像,并让此ImageView
始终与其中的图像保持相同的宽高比,同时具有与单元格相同的宽度。 然后,单元格的高度应与ImageView
的高度相同。
这是我正在使用的代码:
我的自定义UITableViewCell
类:
import UIKit
class ImageTableViewCell: UITableViewCell {
var imageURL: NSURL? {
didSet {
fetchImage()
}
}
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var myImageView: UIImageView!
func fetchImage() {
myImageView?.image = nil
guard let imageURL = self.imageURL else {
return
}
activityIndicator?.startAnimating()
let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
dispatch_async(queue) {
guard let imageData = NSData(contentsOfURL: imageURL) else { return }
dispatch_async(dispatch_get_main_queue()) {
guard imageURL == self.imageURL else { return }
if let image = UIImage(data: imageData) {
self.tweetImage?.image = image
self.tweetImage?.sizeToFit()
} else { self.tweetImage?.image = nil }
self.spinner?.stopAnimating()
}
}
}
func addRatioConstraint(ratio: CGFloat) {
let ratioConstraint = NSLayoutConstraint(item: myImageView, attribute: .Width, relatedBy: .Equal, toItem: myImageView, attribute: .Height, multiplier: ratio, constant: 0)
ratioConstraint.priority = UILayoutPriorityDefaultHigh //important piece of code
myImageView?.addConstraint(ratioConstraint)
}
}
这是UITableViewController
的相关代码:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let mention = mentionSections[indexPath.section].mentions[indexPath.row]
switch mention {
case .Image(let url, let ratio):
guard let imageCell = tableView.dequeueReusableCellWithIdentifier(.Image, forIndexPath: indexPath) as? ImageTableViewCell else { fallthrough }
imageCell.imageURL = url
imageCell.addRatioConstraint(CGFloat(ratio))
return imageCell
//left out code for additional irrelevant cells
}
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let mention = mentionSections[indexPath.section].mentions[indexPath.row]
switch mention {
case .Image(_, _): return 200
default: return 41
}
}
并了解我在使用dequeueReusableCellWithIdentifier
函数的操作(只是为我简化事情的一个扩展):
private extension UITableView {
enum CellIdentifier: String {
case Image = "Image"
case Keyword = "Keyword"
}
func dequeueReusableCellWithIdentifier(cellIdentifier: CellIdentifier, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return self.dequeueReusableCellWithIdentifier(cellIdentifier.rawValue, forIndexPath: indexPath)
}
}
很抱歉有这么多代码,但是我觉得我必须包括所有这些内容。
现在问题了! 我遇到的问题是,当视图第一次加载时,所有内容看起来都很不错,但是当我将设备转为横向,然后再转回纵向时,我失去了长宽比,图像被压缩了。 像这样:
http://i.imgur.com/tcnBfyH.jpg
但是,如果我删除以下代码行(在addRatioConstraint(ratio: CGFloat)
-方法中):
ratioConstraint.priority = UILayoutPriorityDefaultHigh
(这意味着优先级现在是1000,而不是750),一切正常,只是我现在在控制台中打印出一个错误:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fcfd4d3e690 UIImageView:0x7fcfd4e29a70.trailing == UITableViewCellContentView:0x7fcfd4e29900.trailingMargin>",
"<NSLayoutConstraint:0x7fcfd4d3f5c0 UIImageView:0x7fcfd4e29a70.bottom == UITableViewCellContentView:0x7fcfd4e29900.bottomMargin>",
"<NSLayoutConstraint:0x7fcfd4d3f610 UIImageView:0x7fcfd4e29a70.top == UITableViewCellContentView:0x7fcfd4e29900.topMargin>",
"<NSLayoutConstraint:0x7fcfd4d3f660 UIImageView:0x7fcfd4e29a70.leading == UITableViewCellContentView:0x7fcfd4e29900.leadingMargin>",
"<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.height>",
"<NSLayoutConstraint:0x7fcfd4e1f200 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7fcfd4e29900(341)]>",
"<NSLayoutConstraint:0x7fcfd4e1f250 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcfd4e29900(199.5)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.height>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
因此,基本上Xcode
所做的是它打破了我的方面约束,试图解决一些冲突。 而且有效。 在我的脑海中,这应该意味着降低约束的优先级也可以解决问题?
任何帮助将不胜感激,我已经为此努力了几天。
就像在此答案中一样 ,您正在设置可变宽度约束以及尾随和前导约束。 这将导致冲突。
用centerX约束替换尾随/前导约束。
我建议为此使用锚 。
首先,请确保imageView.contentMode = .scaleAspectFill
imageView.translatesAutoreisizingMaskIntoConstraints = false
和imageView.contentMode = .scaleAspectFill
然后,根据需要在每一侧设置锚点。
imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(self.bottomAnchor).isActive = true
您还可以在约束参数中添加..,constant: Float)
,以设置父锚点和imageView
之间的特定距离。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.