StatsHeaderView에서 categoryButton과 todayButton 사이에 spacerView를 두고, todayButton을 오른쪽 끝에 고정하려고 했지만
버튼을 isHidden = true/false로 토글할 때 버튼 정렬이 가운데로 흔들리는 문제가 발생했습니다.
이 문서는 contentHuggingPriority와 contentCompressionResistancePriority(이하 Hugging/Compression)로 해결하는 과정을 정리합니다.
todayButton을 숨겼다가 다시 표시하면, categoryButton이 가운데로 이동하거나 레이아웃이 들쭉날쭉해 보임UIStackView의 distribution = .fill 상태에서 여유 공간을 누가 가져가느냐가 매번 달라짐.fill에서는 가장 낮은 Hugging을 가진 뷰가 여유 공간을 먼저 가져갑니다.arrangedSubviews에서 isHidden = true가 되면 해당 뷰는 레이아웃에서 제외됩니다.categoryButton이 공간을 가져가며 가운데로 치우칠 수 있습니다.핵심은 오른쪽 버튼은 고정, 가운데 여백은 spacer만 흡수하도록 우선순위를 설계하는 것입니다.
categoryButton.setContentHuggingPriority(.defaultLow, for: .horizontal)
categoryButton.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
spacerView.setContentHuggingPriority(.defaultLow, for: .horizontal)
spacerView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
todayButton.setContentHuggingPriority(.required, for: .horizontal)
todayButton.setContentCompressionResistancePriority(.required, for: .horizontal)
todayButton을 required(1000) 로 설정해 오른쪽 끝에서 크기/위치가 흔들리지 않도록 고정합니다.spacerView는 낮은 Hugging/Compression으로 두어 여유 공간을 전담 흡수하게 만듭니다.categoryButton도 낮게 설정해 필요 시 줄어들 수 있도록 합니다. (제목 길이에 따라 레이아웃이 밀리지 않도록)private lazy var hStack = UIStackView(arrangedSubviews: [
categoryButton, spacerView, todayButton
]).then {
$0.axis = .horizontal
$0.alignment = .center
$0.distribution = .fill
}
.fill + spacer 조합은 spacer가 “빈 공간만” 차지하도록 만드는 기본 패턴입니다.todayButton.isHidden = true
UIView.animate(withDuration: 0.25) {
self.layoutIfNeeded()
}
alignment = .center, distribution = .fill인지 확인todayButton)은 required로 지정isHidden 토글 후 애니메이션이 필요하다면 layoutIfNeeded() 래핑categoryButton.titleLabel?.lineBreakMode = .byTruncatingTailspacer.widthAnchor.constraint(greaterThanOrEqualToConstant: 0)로 시작해 상황에 따라 multiplier를 조정UILabel 길이 변화, 이미지 유무 등 변동 상황에서도 예측 가능한 레이아웃을 보장합니다.