이걸로 지난 3 ~ 4 시간 동안 벽에 머리를 박고 있었는데 알아낼 수없는 것 같습니다. 내부에 전체 화면 UITableView가있는 UIViewController가 있고 (화면에 다른 항목이 있으므로 UITableViewController를 사용할 수 없습니다) 자동 레이아웃으로 tableHeaderView의 크기를 조정하고 싶습니다. 말할 필요도없이 그것은 협력하지 않습니다.
아래 스크린 샷을 참조하십시오.
OverviewLabel (예 : “List overview information here.”텍스트)에는 동적 내용이 있기 때문에 자동 레이아웃을 사용하여 크기를 조정하고 수퍼 뷰입니다. 계층 구조의 Paralax Table View 바로 아래에있는 tableHeaderView를 제외하고는 모든 크기가 멋지게 크기 조정되었습니다.
헤더보기의 크기를 조정하는 유일한 방법은 다음 코드를 사용하는 프로그래밍 방식입니다.
CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = headerFrameHeight;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];
이 경우 headerFrameHeight는 다음과 같이 tableViewHeader 높이의 수동 계산입니다 (innerHeaderView는 흰색 영역이거나 두 번째 “View”, headerView는 tableHeaderView 임) .
CGFloat startingY = self.innerHeaderView.frame.origin.y + self.overviewLabel.frame.origin.y;
CGRect overviewSize = [self.overviewLabel.text
boundingRectWithSize:CGSizeMake(290.f, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName: self.overviewLabel.font}
context:nil];
CGFloat overviewHeight = overviewSize.size.height;
CGFloat overviewPadding = ([self.overviewLabel.text length] > 0) ? 10 : 0; // If there's no overviewText, eliminate the padding in the overall height.
CGFloat headerFrameHeight = ceilf(startingY + overviewHeight + overviewPadding + 21.f + 10.f);
수동 계산은 작동하지만 나중에 상황이 변경되면 투박하고 오류가 발생하기 쉽습니다. 내가 할 수 있기를 원하는 것은 다른 곳에서 할 수 있듯이 제공된 제약 조건에 따라 tableHeaderView의 크기를 자동으로 조정하는 것입니다. 하지만 제 삶을 위해 저는 그것을 이해할 수 없습니다.
이것에 대한 여러 게시물이 있지만 명확하지 않아서 나를 더 혼란스럽게 만들었습니다. 다음은 몇 가지입니다.
translatesAutoresizingMaskIntoConstraints 속성을 NO로 변경하는 것은 실제로 의미가 없습니다. 그 이유는 저에게 오류가 발생하고 어쨌든 개념적으로 이해가되지 않기 때문입니다.
어떤 도움이라도 정말 감사하겠습니다!
편집 1 :
TomSwift의 제안 덕분에 알아낼 수있었습니다. 개요의 높이를 수동으로 계산하는 대신 다음과 같이 계산 한 다음 이전과 같이 tableHeaderView를 다시 설정할 수 있습니다.
[self.headerView setNeedsLayout];
[self.headerView layoutIfNeeded];
CGFloat height = [self.innerHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + self.innerHeaderView.frame.origin.y; // adding the origin because innerHeaderView starts partway down headerView.
CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = height;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];
편집 2 : 다른 사람들이 언급했듯이 편집 1에 게시 된 솔루션이 viewDidLoad에서 작동하지 않는 것 같습니다. 그러나 viewWillLayoutSubviews에서 작동하는 것 같습니다. 아래 예제 코드 :
// Note 1: The variable names below don't match the variables above - this is intended to be a simplified "final" answer.
// Note 2: _headerView was previously assigned to tableViewHeader (in loadView in my case since I now do everything programatically).
// Note 3: autoLayout code can be setup programatically in updateViewConstraints.
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[_headerWrapper setNeedsLayout];
[_headerWrapper layoutIfNeeded];
CGFloat height = [_headerWrapper systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = _headerWrapper.frame;
headerFrame.size.height = height;
_headerWrapper.frame = headerFrame;
_tableView.tableHeaderView = _headerWrapper;
}
답변
UIView systemLayoutSizeFittingSize:
헤더보기의 최소 경계 크기를 얻으려면 메서드 를 사용해야합니다 .
이 Q / A에서이 API 사용에 대한 추가 논의를 제공합니다.
답변
나는 정말로 이것과 싸웠고 프레임이 viewDidLoad에 설정되지 않았기 때문에 viewDidLoad에 설정을 꽂아도 작동하지 않았습니다. 또한 헤더의 캡슐화 된 자동 레이아웃 높이가 0으로 줄어들고있는 수많은 지저분한 경고로 끝났습니다. Form 프레젠테이션에서 tableView를 표시 할 때만 iPad에서 문제를 발견했습니다.
나를 위해 문제를 해결 한 것은 viewDidLoad가 아닌 viewWillLayoutSubviews에서 tableViewHeader를 설정하는 것입니다.
func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if tableView.tableViewHeaderView == nil {
let header: MyHeaderView = MyHeaderView.createHeaderView()
header.setNeedsUpdateConstraints()
header.updateConstraintsIfNeeded()
header.frame = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), CGFloat.max)
var newFrame = header.frame
header.setNeedsLayout()
header.layoutIfNeeded()
let newSize = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
newFrame.size.height = newSize.height
header.frame = newFrame
self.tableView.tableHeaderView = header
}
}
답변
애니메이션을 사용하거나 사용하지 않고 자동 레이아웃을 사용하여 표 머리글의 크기를 조정하는 우아한 방법을 찾았습니다.
View Controller에 추가하기 만하면됩니다.
func sizeHeaderToFit(tableView: UITableView) {
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
var frame = headerView.frame
frame.size.height = height
headerView.frame = frame
tableView.tableHeaderView = headerView
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
}
}
동적으로 변경되는 레이블에 따라 크기를 조정하려면 :
@IBAction func addMoreText(sender: AnyObject) {
self.label.text = self.label.text! + "\nThis header can dynamically resize according to its contents."
}
override func viewDidLayoutSubviews() {
// viewDidLayoutSubviews is called when labels change.
super.viewDidLayoutSubviews()
sizeHeaderToFit(tableView)
}
제약 조건의 변경 사항에 따라 크기 조정을 애니메이션하려면 :
@IBOutlet weak var makeThisTallerHeight: NSLayoutConstraint!
@IBAction func makeThisTaller(sender: AnyObject) {
UIView.animateWithDuration(0.3) {
self.tableView.beginUpdates()
self.makeThisTallerHeight.constant += 20
self.sizeHeaderToFit(self.tableView)
self.tableView.endUpdates()
}
}
이것이 작동하는지 보려면 AutoResizingHeader 프로젝트를 참조하십시오.
https://github.com/p-sun/Swift2-iOS9-UI
답변
이 솔루션은 tableHeaderView의 크기를 조정하고 viewDidLayoutSubviews()
여기에 다른 답변 중 일부를 사용 하는 방법 에서 무한 루프를 방지 합니다.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
var headerFrame = headerView.frame
// comparison necessary to avoid infinite loop
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
tableView.tableHeaderView = headerView
}
}
}
이 게시물도 참조하십시오 : https://stackoverflow.com/a/34689293/1245231
답변
systemLayoutSizeFittingSize :를 사용하는 솔루션은 헤더보기가 각보기 모양에서 한 번만 업데이트되는 경우 작동합니다. 제 경우에는 헤더보기가 상태 변경을 반영하기 위해 여러 번 업데이트되었습니다. 그러나 systemLayoutSizeFittingSize : 항상 동일한 크기를보고했습니다. 즉, 첫 번째 업데이트에 해당하는 크기입니다.
systemLayoutSizeFittingSize를 얻으려면 : 각 업데이트 후 올바른 크기를 반환하려면 먼저 테이블 헤더 뷰를 업데이트하고 다시 추가하기 전에 제거해야했습니다.
self.listTableView.tableHeaderView = nil;
[self.headerView removeFromSuperview];
답변
이것은 ios10 및 Xcode 8에서 나를 위해 일했습니다.
func layoutTableHeaderView() {
guard let headerView = tableView.tableHeaderView else { return }
headerView.translatesAutoresizingMaskIntoConstraints = false
let headerWidth = headerView.bounds.size.width;
let temporaryWidthConstraints = NSLayoutConstraint.constraintsWithVisualFormat("[headerView(width)]", options: NSLayoutFormatOptions(rawValue: UInt(0)), metrics: ["width": headerWidth], views: ["headerView": headerView])
headerView.addConstraints(temporaryWidthConstraints)
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let headerSize = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
let height = headerSize.height
var frame = headerView.frame
frame.size.height = height
headerView.frame = frame
self.tableView.tableHeaderView = headerView
headerView.removeConstraints(temporaryWidthConstraints)
headerView.translatesAutoresizingMaskIntoConstraints = true
}
답변
머리글보기와 바닥 글 모두에서 작동합니다. 머리글을 바닥 글로 바꿉니다.
func sizeHeaderToFit() {
if let headerView = tableView.tableHeaderView {
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
var frame = headerView.frame
frame.size.height = height
headerView.frame = frame
tableView.tableHeaderView = headerView
}
}