I want to achieve a "show more" effect in my view. The desired effect is as follows(sorry for my poor painting), the view's height is set to a specific value at first(such as 304), and when I click the "check more" button, the view's height will return to its original height.

In my demo, the image always covered superview, and the contentLabel disappear at first, just like the gif below. I tried to set setContentCompressionResistancePriority and setContentHuggingPriority, but it's not working.
I have two questions. Firstly how to make the image not to cover it's superview, and just show a part of it when its superview's height is not enough for imageView to show completely. Second, the contentLabel should not disappear at first, I noticed that it is because the label does not know its height at first, so the height constraint is 0, but how to calculate the right height for the content label so that it can be shown on screen even the superview's height is not enough.
Here is my code, I have tried half a day but still not a clue. Thanks for helping:
import UIKit
import SnapKit
import SDWebImage
class ViewController: UIViewController {
var isExpanding = false
var defaultHeightConstraint: Constraint?
private lazy var panelView: UIView = {
let view = UIView()
view.layer.masksToBounds = true
return view
}()
private lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fill
return stackView
}()
private lazy var textPanelView: UIView = {
let view = UIView()
view.backgroundColor = .gray
return UIView()
}()
private lazy var textTitleLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 16)
label.textColor = .black
return label
}()
private lazy var textContentLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 12)
label.textColor = .black
label.numberOfLines = 0
return label
}()
private lazy var imagePanelView: UIView = {
let view = UIView()
view.backgroundColor = .cyan
view.layer.masksToBounds = true
return UIView()
}()
private lazy var imageTitleLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 16)
label.textColor = .black
return label
}()
private lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
view.layer.masksToBounds = true
return imageView
}()
private lazy var expandPanel: UIView = {
UIView()
}()
private lazy var expandBtnBgView: UIView = {
let view = UIView()
return view
}()
private lazy var expandBtn: UIButton = {
let button = UIButton()
button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
button.setTitleColor(.systemGreen, for: .normal)
button.setTitle("Check More", for: .normal)
button.addTarget(self, action: #selector(onClickExpandBtn), for: .touchUpInside)
button.backgroundColor = .white
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
setupModel()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillLayoutSubviews() {
}
private func setupUI() {
view.backgroundColor = .white
view.addSubview(panelView)
panelView.addSubview(stackView)
stackView.addArrangedSubview(textPanelView)
stackView.addArrangedSubview(imagePanelView)
textPanelView.addSubview(textTitleLabel)
textPanelView.addSubview(textContentLabel)
imagePanelView.addSubview(imageTitleLabel)
imagePanelView.addSubview(imageView)
panelView.addSubview(expandPanel)
expandPanel.addSubview(expandBtnBgView)
expandBtnBgView.addSubview(expandBtn)
panelView.snp.makeConstraints { make in
make.top.equalToSuperview().inset(40)
make.left.right.equalToSuperview().inset(16)
defaultHeightConstraint = make.height.lessThanOrEqualTo(304).constraint
}
defaultHeightConstraint?.isActive = true
stackView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
textPanelView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
}
textTitleLabel.snp.makeConstraints { make in
make.left.top.equalToSuperview()
make.height.equalTo(22)
}
textContentLabel.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(textTitleLabel.snp.bottom).offset(12)
make.bottom.equalToSuperview().inset(24)
}
imagePanelView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
}
imageTitleLabel.snp.makeConstraints { make in
make.top.equalToSuperview()
make.left.equalToSuperview()
make.height.equalTo(22)
}
imageView.snp.makeConstraints { make in
make.top.equalTo(imageTitleLabel.snp.bottom).offset(12)
make.left.right.equalToSuperview().inset(16)
make.width.equalTo(UIScreen.main.bounds.width - 64)
make.height.equalTo(0)
make.bottom.equalToSuperview().inset(24)
}
expandPanel.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(86)
make.bottom.equalToSuperview()
}
expandBtnBgView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(46)
make.bottom.equalToSuperview()
}
expandBtn.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().inset(16)
}
// this code did not work
textPanelView.setContentHuggingPriority(.defaultHigh, for: .vertical)
textPanelView.setContentCompressionResistancePriority(.required, for: .vertical)
textContentLabel.setContentCompressionResistancePriority(.required, for: .vertical)
textContentLabel.setContentHuggingPriority(.required, for: .vertical)
imagePanelView.setContentHuggingPriority(.defaultLow, for: .vertical)
imagePanelView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
imageView.setContentHuggingPriority(.defaultLow, for: .vertical)
imageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
}
private func setupModel() {
// setupText
textTitleLabel.text = "Package Title"
textContentLabel.text = "Beef\nCheese Beef\nDouble Cheese Beef\nDouble Cheese Beef\nDouble Cheese Beef\nDouble Cheese Beef\nDouble Cheese Beef "
// setupImage
imageTitleLabel.text = "Image Title"
let imgString = "https://i.postimg.cc/Wzxfw1JY/chic.jpg"
imageView.sd_setImage(with: URL(string: imgString)) { [weak self] image, _, _, _ in
guard let self = self, let image = image else { return }
let imgSize = image.size
let actualWidth = UIScreen.main.bounds.width - 64
let actualHeight = (actualWidth / imgSize.width) * imgSize.height
self.imageView.snp.updateConstraints { make in
make.width.equalTo(actualWidth)
make.height.equalTo(actualHeight)
}
}
}
@objc func onClickExpandBtn() {
isExpanding = !isExpanding
if isExpanding {
defaultHeightConstraint?.isActive = false
expandBtn.setTitle("Collapse", for: .normal)
} else {
defaultHeightConstraint?.isActive = true
expandBtn.setTitle("Check More", for: .normal)
}
}
}

I'd use a different approach. I would cover the botton half of the imageView with an overlay. The overlay hides the bottom half of the image until you tap on "Check More". When you tap "Check More", you hide the overlay view (set its height to zero), revealing the remaining portion of the imageView. With this approach you don't have to mess with content hugging or compression resistance priorities.
You had a couple other bugs in your code, but here's a working solution.