仓前iOS研究组首页投稿(暂停使用,暂停投稿)程序员

关于UIImageView自适应的问题

2016-03-16  本文已影响5835人  阿呆少爷

因为不同的机型的长宽比不一样,导致同样的图片难于适应所有的屏幕。一般情况下,需求是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也拥有这种特性就好了啊,指定宽度,高度上的约束自适应,省多少事啊。

上一篇下一篇

猜你喜欢

热点阅读