因为不同的机型的长宽比不一样,导致同样的图片难于适应所有的屏幕。一般情况下,需求是image view的宽度跟屏幕一样,根据实际情况调整image view的高度。比如一张685*309
像素的图片,在iPhone6上的size是375*167
,而在iPhone6 Plus上则是414*186
。为了达到最优的显示效果,必须根据图片的size动态调整cell的高度。
图片的size可以从URL获取,也可以在SDWebImage这样的库里面的completion block里面获取,当然为了达到最好的效果,在URL中指明图片的size是更好的。
在渲染cell的时候,先根据图片URL的宽长比,得到imageview合理的高度,然后给imageview设置上这个高度约束。我发现一个有趣的问题,就是AutoLayout会影响UIImageView的contentMode,即使指定了ScaleAspectFit
,同样会拉伸图片,造成变形。
final class TestViewCellUseConstraint : UITableViewCell {
var imgViewHeightConstraint : Constraint?
lazy var imgView : UIImageView = {
let imgView = UIImageView()
imgView.contentMode = UIViewContentMode.ScaleAspectFill
imgView.clipsToBounds = true
self.contentView.addSubview(imgView)
return imgView
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.contentView.backgroundColor = UIColor.redColor()
self.imgView.snp_makeConstraints { (make) -> Void in
make.leading.equalTo(0)
make.trailing.equalTo(0)
make.top.equalTo(8)
//给一个默认的高度值
self.imgViewHeightConstraint = make.height.equalTo(154.5).constraint
make.bottom.equalTo(self.contentView.snp_bottom).offset(0)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
final class TestViewController : YWSBaseUITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = .None
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let image = UIImage(named: "aliyun_sz")!
let cell = TestViewCellUseConstraint()
cell.imgView.image = image
cell.imgViewHeightConstraint?.updateOffset(floor(DeviceUtils.getScreenWidth()/(image.size.width / image.size.height)))
cell.setNeedsUpdateConstraints()
return cell
}
}
最后需要注意的是,在计算高度的时候应该避免出现少数点的约束,否则可能产生下面这样的约束冲突。image view的高度计算出来是186.753280639648
,而content view计算出来的高度则是186.667
,二者不一样,但是我指明二者的高度是一样的,iOS会选择丢掉一个约束。
2016-03-16 18:02:06.930 CloudConsoleApp[74807:15177377] 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.
(
"<SnapKit.LayoutConstraint:0x7fab951e80d0@/Users/henshao/cloudconsole-iOS/CloudConsoleApp/YWSMyViewController.swift#336 UIImageView:0x7fab95537d80.top == UITableViewCellContentView:0x7fab95537970.top>",
"<SnapKit.LayoutConstraint:0x7fab951e8620@/Users/henshao/cloudconsole-iOS/CloudConsoleApp/YWSMyViewController.swift#336 UIImageView:0x7fab95537d80.height == 186.753280639648>",
"<SnapKit.LayoutConstraint:0x7fab951e8a60@/Users/henshao/cloudconsole-iOS/CloudConsoleApp/YWSMyViewController.swift#336 UIImageView:0x7fab95537d80.bottom == UITableViewCellContentView:0x7fab95537970.bottom>",
"<NSLayoutConstraint:0x7fab951e9940 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fab95537970(186.667)]>"
)
Will attempt to recover by breaking constraint
<SnapKit.LayoutConstraint:0x7fab951e8620@/Users/henshao/cloudconsole-iOS/CloudConsoleApp/YWSMyViewController.swift#336 UIImageView:0x7fab95537d80.height == 186.753280639648>
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.
UILabel的长度和宽度是根据字体自适应的,如果UIImageView也拥有这种特性就好了啊,指定宽度,高度上的约束自适应,省多少事啊。