Saya telah membenturkan kepala saya ke dinding dengan ini selama 3 atau 4 jam terakhir dan sepertinya saya tidak bisa memahaminya. Saya memiliki UIViewController dengan UITableView layar penuh di dalamnya (ada beberapa hal lain di layar, itulah sebabnya saya tidak dapat menggunakan UITableViewController) dan saya ingin tableHeaderView saya diubah ukurannya dengan autolayout. Tak perlu dikatakan, itu tidak bekerja sama.
Lihat gambar di bawah.
Karena label overview (mis. Teks "Cantumkan informasi ikhtisar di sini.") Memiliki konten dinamis, saya menggunakan autolayout untuk mengubah ukurannya dan ini adalah tampilan super. Saya telah mengubah ukurannya dengan baik, kecuali untuk tableHeaderView, yang berada tepat di bawah Paralax Table View di hiearchy.
Satu-satunya cara yang saya temukan untuk mengubah ukuran tampilan header itu secara terprogram, dengan kode berikut:
CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = headerFrameHeight;
self.headerView.frame = headerFrame;
[self.listTableView setTableHeaderView:self.headerView];
Dalam kasus ini, headerFrameHeight adalah kalkulasi manual dari tinggi tableViewHeader sebagai berikut (innerHeaderView adalah area putih, atau "View" kedua, headerView adalah 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);
Penghitungan manual berfungsi, tetapi kikuk dan rawan kesalahan jika ada perubahan di masa mendatang. Apa yang ingin saya lakukan adalah mengubah ukuran otomatis tableHeaderView berdasarkan batasan yang disediakan, seperti yang Anda bisa lakukan di tempat lain. Tapi untuk hidupku, aku tidak bisa memahaminya.
Ada beberapa posting di SO tentang ini, tetapi tidak ada yang jelas dan akhirnya lebih membingungkan saya. Ini beberapa:
Apakah mungkin menggunakan AutoLayout dengan tableHeaderView milik UITableView?
tinggi tampilan header tabel salah saat menggunakan tata letak otomatis, IB, dan ukuran font
Tidaklah masuk akal untuk mengubah properti translatesAutoresizingMaskIntoConstraints menjadi NO, karena hal itu hanya menyebabkan kesalahan bagi saya dan tidak masuk akal secara konseptual.
Bantuan apapun akan sangat dihargai!
EDIT 1: Berkat saran TomSwift, saya dapat mengetahuinya. Alih-alih menghitung secara manual ketinggian ikhtisar, saya dapat menghitungnya untuk saya sebagai berikut dan kemudian mengatur ulang tableHeaderView seperti sebelumnya.
[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];
Sunting 2: Seperti yang telah dicatat orang lain, solusi yang diposting di Sunting 1 tampaknya tidak berfungsi di viewDidLoad. Namun, tampaknya berfungsi di viewWillLayoutSubviews. Contoh kode di bawah ini:
// 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;
}
sumber
setTableHeaderView
tidak berfungsi di Xcode6. Masalahnya adalah sel-sel tersebut tumpang tindih dengan tableHeaderView. Namun, ini berfungsi pada Xcode5Jawaban:
Anda perlu menggunakan
UIView systemLayoutSizeFittingSize:
metode ini untuk mendapatkan ukuran batas minimum tampilan header Anda.Saya memberikan pembahasan lebih lanjut tentang penggunaan API ini dalam Tanya Jawab ini:
Bagaimana cara mengubah ukuran superview agar sesuai dengan semua subview dengan autolayout?
sumber
Saya benar-benar berjuang dengan yang satu ini dan memasukkan pengaturan ke viewDidLoad tidak berfungsi untuk saya karena bingkai tidak disetel di viewDidLoad, saya juga berakhir dengan banyak peringatan yang berantakan di mana tinggi tata letak otomatis yang dienkapsulasi dari header dikurangi menjadi 0 Saya hanya memperhatikan masalah di iPad saat mempresentasikan tableView dalam presentasi Formulir.
Apa yang memecahkan masalah bagi saya adalah menyetel tableViewHeader di viewWillLayoutSubviews daripada di viewDidLoad.
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 } }
sumber
Saya telah menemukan cara elegan untuk menggunakan tata letak otomatis untuk mengubah ukuran header tabel, dengan dan tanpa animasi.
Cukup tambahkan ini ke Pengontrol Tampilan Anda.
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() } }
Untuk mengubah ukuran sesuai dengan label yang berubah secara dinamis:
@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) }
Untuk menganimasikan perubahan ukuran sesuai dengan perubahan dalam batasan:
@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() } }
Lihat proyek AutoResizingHeader untuk melihat ini beraksi. https://github.com/p-sun/Swift2-iOS9-UI
sumber
@IBOutlet makeThisTaller
dan@IBAction fun makeThisTaller
suka dalam contoh. Juga, batasi semua sisi label Anda ke tableViewHeader (misalnya atas, bawah, kiri, dan kanan).lblFeedDescription.preferredMaxLayoutWidth = lblFeedDescription.bounds.width
mana label adalah salah satu yang ingin saya tingkatkan ukurannya. Terima kasih!Solusi ini mengubah ukuran tableHeaderView dan menghindari loop tak terbatas dalam
viewDidLayoutSubviews()
metode yang saya alami dengan beberapa jawaban lain di sini: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 } } }
Lihat juga posting ini: https://stackoverflow.com/a/34689293/1245231
sumber
Solusi Anda menggunakan systemLayoutSizeFittingSize: berfungsi jika tampilan header hanya diperbarui satu kali pada setiap tampilan tampilan. Dalam kasus saya, tampilan tajuk diperbarui beberapa kali untuk mencerminkan perubahan status. Tetapi systemLayoutSizeFittingSize: selalu melaporkan ukuran yang sama. Artinya, ukurannya sesuai dengan pembaruan pertama.
Untuk mendapatkan systemLayoutSizeFittingSize: untuk mengembalikan ukuran yang benar setelah setiap pembaruan, saya harus terlebih dahulu menghapus tampilan header tabel sebelum memperbaruinya dan menambahkannya kembali:
self.listTableView.tableHeaderView = nil; [self.headerView removeFromSuperview];
sumber
Ini berfungsi untuk saya di ios10 dan 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 }
sumber
Ini berfungsi untuk tampilan header dan footer, cukup ganti header dengan footer
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 } }
sumber
Untuk iOS 12 dan yang lebih baru, langkah-langkah berikut akan memastikan tata letak otomatis berfungsi dengan baik di tabel dan header Anda.
sumber
Dalam kasus saya
viewDidLayoutSubviews
bekerja lebih baik.viewWillLayoutSubviews
menyebabkan garis putih atableView
muncul. Juga saya menambahkan memeriksa apakahheaderView
objek saya sudah ada.- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; if ( ! self.userHeaderView ) { // Setup HeaderView self.userHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"SSUserHeaderView" owner:self options:nil] objectAtIndex:0]; [self.userHeaderView setNeedsLayout]; [self.userHeaderView layoutIfNeeded]; CGFloat height = [self.userHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; CGRect headerFrame = self.userHeaderView.frame; headerFrame.size.height = height; self.userHeaderView.frame = headerFrame; self.tableView.tableHeaderView = self.userHeaderView; // Update HeaderView with data [self.userHeaderView updateWithProfileData]; } }
sumber
Sangat mungkin untuk menggunakan berbasis AutoLayout generik
UIView
dengan struktur subview dalam AL apa pun sebagaitableHeaderView
.Satu-satunya hal yang dibutuhkan adalah mengatur yang sederhana
tableFooterView
sebelumnya!Mari
self.headerView
adalah beberapa berbasis kendalaUIView
.- (void)viewDidLoad { ........................ self.tableView.tableFooterView = [UIView new]; [self.headerView layoutIfNeeded]; // to set initial size self.tableView.tableHeaderView = self.headerView; [self.tableView.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor].active = YES; [self.tableView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor].active = YES; [self.tableView.topAnchor constraintEqualToAnchor:self.headerView.topAnchor].active = YES; // and the key constraint [self.tableFooterView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor].active = YES; }
Jika
self.headerView
mengubah ketinggian di bawah rotasi UI, kita harus mengimplementasikannya- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [coordinator animateAlongsideTransition: ^(id<UIViewControllerTransitionCoordinatorContext> context) { // needed to resize header height self.tableView.tableHeaderView = self.headerView; } completion: NULL]; }
Seseorang dapat menggunakan kategori ObjC untuk tujuan ini
@interface UITableView (AMHeaderView) - (void)am_insertHeaderView:(UIView *)headerView; @end @implementation UITableView (AMHeaderView) - (void)am_insertHeaderView:(UIView *)headerView { NSAssert(self.tableFooterView, @"Need to define tableFooterView first!"); [headerView layoutIfNeeded]; self.tableHeaderView = headerView; [self.leadingAnchor constraintEqualToAnchor:headerView.leadingAnchor].active = YES; [self.trailingAnchor constraintEqualToAnchor:headerView.trailingAnchor].active = YES; [self.topAnchor constraintEqualToAnchor:headerView.topAnchor].active = YES; [self.tableFooterView.trailingAnchor constraintEqualToAnchor:headerView.trailingAnchor].active = YES; } @end
Dan juga ekstensi Swift
extension UITableView { func am_insertHeaderView2(_ headerView: UIView) { assert(tableFooterView != nil, "Need to define tableFooterView first!") headerView.layoutIfNeeded() tableHeaderView = headerView leadingAnchor.constraint(equalTo: headerView.leadingAnchor).isActive = true trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true tableFooterView?.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true } }
sumber
Solusi ini bekerja dengan sempurna untuk saya:
https://spin.atomicobject.com/2017/08/11/swift-extending-uitableviewcontroller/
Ini memperluas UITableViewController. Tetapi jika Anda hanya menggunakan UITableView, ini akan tetap berfungsi, cukup perpanjang UITableView, bukan UITableViewController. Panggil metode
sizeHeaderToFit()
atausizeFooterToFit()
setiap kali ada kejadian yang mengubahtableViewHeader
ketinggian.sumber
Disalin dari postingan ini
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if let headerView = tableView.tableHeaderView { let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).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 } } }
sumber