はじめに
この記事ではUIImageViewの横幅をディスプレイの幅に合わせ、かつ横幅の比率を1とした場合のオリジナル画像と同じ高さの比率で表示する方法を紹介しています。
環境
- Swift5
- Xcode12.4
- iOS13
実装方法
結論から書くと、UIImageViewの高さ=UIImageViewの横幅✕(画像の高さ/画像の幅)
で計算して設定しています。
コード
FlexibleHeightImageView
としてクラスを作成しました。
使い方のサンプルとしてSampleFlexibleHeightImageViewController
も記載しておきます。
import UIKit
class FlexibleHeightImageView: UIView {
private var imageView = UIImageView()
@IBInspectable
public var image: UIImage? {
didSet {
imageView.image = image
updateImageViewConstraints()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initialize()
}
private func initialize() {
addSubview(imageView)
imageView.contentMode = .scaleAspectFit
imageView.translatesAutoresizingMaskIntoConstraints = false
}
override func layoutSubviews() {
super.layoutSubviews()
if let img = image {
let height = self.frame.size.width * (img.size.height / img.size.width)
imageView.heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
private func updateImageViewConstraints() {
imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
}
import UIKit
class SampleFlexibleHeightImageViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let fImageView = FlexibleHeightImageView(frame: .zero)
view.addSubview(fImageView)
fImageView.translatesAutoresizingMaskIntoConstraints = false
fImageView.image = UIImage(named: "img")
fImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 200).isActive = true
fImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
fImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
}
}
コードの説明
imageViewのcontentMode
をscaleAspectFit
としています。
こうすることで画像全体をimageViewに表示するように設定します。このままでは画像全体が収まるように表示されるため、画像とimageView間に余白ができてしまいます。余白が空かないように画像全体をimageViewに表示するために次の計算式で動的に高さを設定します。
imageView.contentMode = .scaleAspectFit
画像が取得できた場合にUIImageViewの高さ=UIImageViewの横幅✕(画像の高さ/画像の幅)
で横幅比を1とし、それに対して高さ比を計算して動的に設定しています。
let height = self.frame.size.width * (img.size.height / img.size.width)
imageView.heightAnchor.constraint(equalToConstant: height).isActive = true
fImageView(FlexibleHeightImageView)
の高さを固定値としないことがポイントとなります。
高さ200とかしてしまうとその値で表示されてしまうのでお気をつけください。
imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 200).isActive = true
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
まとめ
仕事をしているとわりかし要望があるかなと思いますので役に立ったら嬉しいです。
コメント