क्या UITableView की तालिकाHeaderView के साथ AutoLayout का उपयोग करना संभव है?


97

जब से मुझे पता चला कि AutoLayoutमैं इसे हर जगह उपयोग करता हूं, अब मैं इसे एक के साथ उपयोग करने की कोशिश कर रहा हूं tableHeaderView

मैं एक बनाया subclassका UIViewजोड़ा सब कुछ (लेबल आदि ...) मैं, उनके बाधाओं के साथ करना चाहता था तो मैं इस जोड़ा CustomViewकरने के लिए UITableView' tableHeaderView

सब कुछ ठीक काम करता है सिवाय UITableViewहमेशा ऊपर के डिस्प्ले को छोड़कर CustomView, ऊपर से मेरा मतलब है कि CustomViewयह नीचे है UITableViewइसलिए इसे नहीं देखा जा सकता है!

ऐसा लगता है कि कोई फर्क नहीं पड़ता कि मुझे क्या करना, heightकी UITableView' tableHeaderViewहै हमेशा 0 (ताकि चौड़ाई, x और y है)।

मेरा प्रश्न: क्या यह संभव है कि फ्रेम को मैन्युअल रूप से सेट किए बिना इसे पूरा किया जाए ?

संपादित करें:CustomView ' subviewमैं उपयोग कर रहा हूँ कि इन बाधाओं है:

_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];

मैं एक आसान पुस्तकालय 'KeepLayout' का उपयोग कर रहा हूं क्योंकि लेखन की बाधाएं हमेशा के लिए बंद हो जाती हैं और एक ही बाधा के लिए बहुत सी लाइन खींचती हैं, लेकिन तरीके स्वयं-व्याख्यात्मक हैं।

और UITableViewइन बाधाओं है:

_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];

_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;

मुझे नहीं पता कि मुझे कुछ बाधाओं को सीधे पर सेट करना है CustomView, मुझे लगता है कि कस्टमव्यू की ऊंचाई को UILabel"शीर्षक" में बाधाओं से निर्धारित किया जाता है।

EDIT 2: एक अन्य जांच के बाद ऐसा लगता है कि CustomView की ऊंचाई और चौड़ाई की सही गणना की गई है, लेकिन CustomView के शीर्ष अभी भी UITableView के शीर्ष की तुलना में समान स्तर पर है और वे स्क्रॉल करते समय एक साथ चलते हैं।


हाँ यह संभव है। क्या आप वह कोड दिखा सकते हैं जिसका आप उपयोग कर रहे हैं? हेडर दृश्य पर आपके द्वारा स्थापित की गई बाधाओं को जानने के बिना यह सलाह देना मुश्किल है।
जटार्टन

आपके लिए इसे पूरा करने का एक आसान तरीका यह है कि IB में उस दृश्य को tableView में जोड़ दें..जबकि दृश्य को उसी दृश्य में बनाएं जिसमें तालिका दृश्य है और इसे तालिका में खींचें
मरियम के।

मैं आईबी से बचने की कोशिश कर रहा हूं जो मैं कर सकता हूं, अब तक मुझे इसका उपयोग नहीं करना था, अगर मुझे यह काम करने के लिए नहीं मिल सकता है तो मैं आईबी के साथ प्रयास
करूंगा

1
Apple डेवलपरों को सलाह देता है कि जब भी ऑटोलैयट की बात हो तो वह आईबी का उपयोग करें। यह वास्तव में असंगतता की बहुत सारी समस्याओं से बचने में मदद करता है।
मरियम के।

सच्चा पूर्ण
ऑटोलैयूट

जवाबों:


134

मैंने यहां एक समान प्रश्न पूछा और उत्तर दिया । सारांश में, मैं एक बार हेडर जोड़ता हूं और आवश्यक ऊंचाई खोजने के लिए इसका उपयोग करता हूं। उस ऊंचाई को फिर हेडर पर लागू किया जा सकता है, और हेडर दूसरी बार परिवर्तन को प्रतिबिंबित करने के लिए सेट किया गया है।

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.header = [[SCAMessageView alloc] init];
    self.header.titleLabel.text = @"Warning";
    self.header.subtitleLabel.text = @"This is a message with enough text to span multiple lines. This text is set at runtime and might be short or long.";

    //set the tableHeaderView so that the required height can be determined
    self.tableView.tableHeaderView = self.header;
    [self.header setNeedsLayout];
    [self.header layoutIfNeeded];
    CGFloat height = [self.header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    //update the header's frame and set it again
    CGRect headerFrame = self.header.frame;
    headerFrame.size.height = height;
    self.header.frame = headerFrame;
    self.tableView.tableHeaderView = self.header;
}

यदि आपके पास मल्टी-लाइन लेबल हैं, तो यह प्रत्येक लेबल के पसंदीदामैक्स लाईटवॉथ को सेट करने वाले कस्टम दृश्य पर भी निर्भर करता है:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
    self.subtitleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.subtitleLabel.frame);
}

या शायद अधिक आम तौर पर:

override func layoutSubviews() {
    super.layoutSubviews()  
    for view in subviews {
        guard let label = view as? UILabel where label.numberOfLines == 0 else { continue }
        label.preferredMaxLayoutWidth = CGRectGetWidth(label.frame)
    }
}

अपडेट जनवरी 2015

दुर्भाग्य से यह अभी भी आवश्यक लगता है। यहाँ लेआउट प्रक्रिया का एक तेज संस्करण है:

tableView.tableHeaderView = header
header.setNeedsLayout()
header.layoutIfNeeded()
header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
tableView.tableHeaderView = header

मैंने UITableView पर इसे एक्सटेंशन में ले जाना उपयोगी पाया है:

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        header.setNeedsLayout()
        header.layoutIfNeeded()
        header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
        self.tableHeaderView = header
    }
}

उपयोग:

let header = SCAMessageView()
header.titleLabel.text = "Warning"
header.subtitleLabel.text = "Warning message here."
tableView.setAndLayoutTableHeaderView(header)

8
उपयोग करने का एक विकल्प उपयोग preferredMaxLayoutWidthकरने से पहले हेडर दृश्य पर एक चौड़ाई की बाधा (तालिका दृश्य की चौड़ाई के बराबर) जोड़ रहा है systemLayoutSizeFittingSize:
बेन्जोन

2
नोट: यदि आप अनुभव कर रहे हैं कि हेडर पहली कोशिकाओं के ऊपर है, तो आप हेडर प्रॉपर्टी को रीसेट करना भूल गए हैंself.tableView.tableHeaderView
Laszlo

7
अक्सर यह मुझे चकित करता है कि इस तरह से पूरी तरह से तुच्छ कुछ करने के लिए कितना मुश्किल हो सकता है।
टायलरजम्स 18

5
नोट: यदि आपको let height = header.systemLayoutSizeFittingSize(CGSizeMake(CGRectGetWidth(self.bounds), 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
तालिका दृश्य के

3
जस्ट यूज़ header.setNeedsLayout() header.layoutIfNeeded() header.frame.size = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) self.tableHeaderView = headeriOS 10.2 पर काम करेगा
केसोंग Xie

24

मैं (कोड में) बाधाओं का उपयोग करके एक हेडर दृश्य जोड़ने में असमर्थ रहा हूं। यदि मैं अपने दृश्य को एक चौड़ाई और / या ऊँचाई की बाधा देता हूं, तो मुझे संदेश के साथ एक दुर्घटना मिलती है:

 "terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super."

जब मैं अपने टेबल व्यू में स्टोरीबोर्ड में एक दृश्य जोड़ता हूं, तो यह कोई बाधा नहीं दिखाता है, और यह हेडर दृश्य के रूप में ठीक काम करता है, इसलिए मुझे लगता है कि हेडर व्यू का प्लेसमेंट बाधाओं का उपयोग नहीं किया गया है। यह उस संबंध में एक सामान्य दृश्य की तरह व्यवहार नहीं करता है।

चौड़ाई स्वचालित रूप से तालिका दृश्य की चौड़ाई है, केवल एक चीज जिसे आपको सेट करने की आवश्यकता है वह है ऊँचाई - मूल मानों को अनदेखा किया जाता है, इसलिए इससे कोई फर्क नहीं पड़ता कि आपने उन लोगों के लिए क्या रखा है। उदाहरण के लिए, इसने ठीक काम किया (जैसा कि रे के लिए 0,0,0,80 है):

UIView *headerview = [[UIView alloc] initWithFrame:CGRectMake(1000,1000, 0, 80)];
headerview.backgroundColor = [UIColor yellowColor];
self.tableView.tableHeaderView = headerview;

मेरे पास वह अपवाद भी था, लेकिन UITableView में एक श्रेणी जोड़ने से यह निश्चित हो गया कि मैंने इसे उस उत्तर में पाया: stackoverflow.com/questions/12610783/…
इसकाASecret

मैं अभी भी कोशिश कर रहा हूं कि आप क्या सुझाव देते हैं, लेकिन कल सुबह, यह 1:34 बजे मैं बिस्तर पर जा रहा हूं, जवाब देने के लिए समय निकालने के लिए बहुत-बहुत धन्यवाद! (लेकिन मैं वास्तव में एक ऊंचाई निर्दिष्ट नहीं करना चाहता हूं, मैं यह चाहूंगा कि मैं कस्टमव्यू में लेबल पर स्थापित बाधाओं से गणना करूं)
इसके

मैंने इसकी कोशिश की है और हाँ फ्रेम के काम को सेट करना है, लेकिन मैं फ्रेम को सेट करने से बचने का एक तरीका ढूंढ रहा था, मैं
देखता रहूँगा

1
मुझे यह अपवाद मिलता है (वर्तमान में 7.1 परीक्षण) यदि जोड़ा हेडर दृश्य है translatesAutoresizingMaskIntoConstraints = NO। अनुवाद को चालू करने से त्रुटि UITableViewसे बचा जाता है - मुझे संदेह है कि 7.1 के रूप में इसके हेडर दृश्य को स्वतः प्राप्त करने का प्रयास नहीं करता है और फ़्रेम पूर्व-सेट के साथ कुछ चाहता है।
बेन्जोन

16

मैंने यहां बहुत सारी अनावश्यक चीजें करते हुए बहुत सारी विधियाँ देखीं, लेकिन हेडर दृश्य में ऑटो लेआउट का उपयोग करने के लिए आपको उतनी आवश्यकता नहीं है। आपको बस आपको xib फ़ाइल बनानी होगी, अपनी अड़चनें डालनी होंगी और उसे इस तरह से झटपटाना होगा:

func loadHeaderView () {
        guard let headerView = Bundle.main.loadNibNamed("CourseSearchHeader", owner: self, options: nil)?[0] as? UIView else {
            return
        }
        headerView.autoresizingMask = .flexibleWidth
        headerView.translatesAutoresizingMaskIntoConstraints = true
        tableView.tableHeaderView = headerView
    }

इसने हमारे लिए iOS 11 पर मल्टी-लाइन लेबल्स के साथ डायनामिक हाइट हेडर के साथ भी काम किया।
बेन Scheirman

1
आप IB के लचीलेपन-ऑटोरेस्‍टिंग-ऑप्‍शन को भी हटा सकते हैं।
d4Rk

मैं अपने xFooterView (एक xib / nib के माध्यम से) की ऊंचाई निर्धारित करने की कोशिश कर रहा हूं और फ्रेम, ऊंचाई, लेआउटआईएनडीड (), आदि सेट करने में सफलता नहीं मिल रही थी, लेकिन इस समाधान ने आखिरकार मुझे इसे सेट करने की अनुमति दी।
विक्ज़िला

एक xib फ़ाइल में पूरे दृश्य के लिए ऊँचाई बाधा निर्धारित करना न भूलें।
डेनिस कुटलुबा

6

एक अन्य उपाय है कि हेडर व्यू क्रिएशन को अगले मुख्य थ्रेड कॉल में भेजा जाए:

- (void)viewDidLoad {
    [super viewDidLoad];

    // ....

    dispatch_async(dispatch_get_main_queue(), ^{
        _profileView = [[MyView alloc] initWithNib:@"MyView.xib"];
        self.tableView.tableHeaderView = self.profileView;
    });
}

नोट: यह बग को ठीक करता है जब लोड किए गए दृश्य की एक निश्चित ऊंचाई होती है। मैंने कोशिश नहीं की है जब हेडर की ऊंचाई केवल इसकी सामग्री पर निर्भर करती है।

संपादित करें:

आप इस फ़ंक्शन को लागू करके और इसे कॉल करके इस समस्या का एक क्लीनर समाधान पा सकते हैंviewDidLayoutSubviews

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self sizeHeaderToFit];
}

1
@TussLaszlo ऑटोलेयआउट के tableHeaderViewसाथ छोटी गाड़ी की तरह हैं। कुछ वर्कअराउंड हैं, जैसे यह एक। लेकिन चूंकि मैं इस लिखा था, मैं एक बेहतर और क्लीनर यहाँ समाधान मिल गया है stackoverflow.com/a/21099430/127493 अपने फोन करके - (void)sizeHeaderToFitमेंviewDidLayoutSubviews
मार्टिन

4

कोड:

  extension UITableView {

          func sizeHeaderToFit(preferredWidth: CGFloat) {
            guard let headerView = self.tableHeaderView else {
              return
            }

            headerView.translatesAutoresizingMaskIntoConstraints = false
            let layout = NSLayoutConstraint(
              item: headerView,
              attribute: .Width,
              relatedBy: .Equal,
              toItem: nil,
              attribute:
              .NotAnAttribute,
              multiplier: 1,
              constant: preferredWidth)

            headerView.addConstraint(layout)

            let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
            headerView.frame = CGRectMake(0, 0, preferredWidth, height)

            headerView.removeConstraint(layout)
            headerView.translatesAutoresizingMaskIntoConstraints = true

            self.tableHeaderView = headerView
          }
  }

यह काम करता है। सभी टेबलहेडेरिउ उप साक्षात्कारों के लिए उचित ऑटोलैयट बाधाओं को दूर करें। यदि आप एक भी बाधा याद करते हैं, तो यह काम नहीं करेगा।
abhimuralidharan

4

इस समाधान को विस्तारित करें http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-use-auto-layout/ जो तालिका पाद लेख दृश्य के लिए:

@interface AutolayoutTableView : UITableView

@end

@implementation AutolayoutTableView

- (void)layoutSubviews {
    [super layoutSubviews];

    // Dynamic sizing for the header view
    if (self.tableHeaderView) {
        CGFloat height = [self.tableHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
        CGRect headerFrame = self.tableHeaderView.frame;

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if (height != headerFrame.size.height) {
            headerFrame.size.height = height;
            self.tableHeaderView.frame = headerFrame;
            self.tableHeaderView = self.tableHeaderView;
        }

        [self.tableHeaderView layoutIfNeeded];
    }

    // Dynamic sizing for the footer view
    if (self.tableFooterView) {
        CGFloat height = [self.tableFooterView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
        CGRect footerFrame = self.tableFooterView.frame;

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if (height != footerFrame.size.height) {
            footerFrame.size.height = height;
            self.tableFooterView.frame = footerFrame;
            self.tableFooterView = self.tableFooterView;
        }

        self.tableFooterView.transform = CGAffineTransformMakeTranslation(0, self.contentSize.height - footerFrame.size.height);
        [self.tableFooterView layoutIfNeeded];
    }
}

@end

कल एक दिन बिताया है कि टेबलहैडर को ऑटो आकार / लेआउट को सही ढंग से प्राप्त करने की कोशिश कर रहा है। यह समाधान मेरे लिए काम करता है। बहुत बहुत धन्यवाद।
डोकांग

नमस्ते! क्या आप कृपया self.tableFooterView.transformहिस्सा बता सकते हैं ? क्यों जरूरी है?
vn

@ श्रवण रूपांतरण का उपयोग पादलेख को तालिका दृश्य के निचले भाग में ले जाने के लिए किया जाता है।
k06a

3

आप SystemLayoutSizeFittingSize पद्धति का उपयोग करके आपको एक आकार प्रदान करने के लिए ऑटोलायउट प्राप्त कर सकते हैं ।

फिर आप अपने एप्लिकेशन के लिए फ़्रेम बनाने के लिए इसका उपयोग कर सकते हैं। यह तकनीक तब काम करती है जब आपको आंतरिक रूप से ऑटोलेयूट का उपयोग करने वाले दृश्य के आकार को जानने की आवश्यकता होती है।

स्विफ्ट में कोड जैसा दिखता है

//Create the view
let tableHeaderView = CustomTableHeaderView()

//Set the content
tableHeaderView.textLabel.text = @"Hello world"

//Ask auto layout for the smallest size that fits my constraints    
let size = tableHeaderView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

//Create a frame    
tableHeaderView.frame = CGRect(origin: CGPoint.zeroPoint, size: size)

//Set the view as the header    
self.tableView.tableHeaderView = self.tableHeaderView

या ऑब्जेक्टिव-सी में

//Create the view
CustomTableHeaderView *header = [[CustomTableHeaderView alloc] initWithFrame:CGRectZero];

//Set the content
header.textLabel.text = @"Hello world";

//Ask auto layout for the smallest size that fits my constraints
CGSize size = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

//Create a frame
header.frame = CGRectMake(0,0,size.width,size.height);

//Set the view as the header  
self.tableView.tableHeaderView = header

यह भी ध्यान दिया जाना चाहिए कि इस विशेष उदाहरण में, आपके उपवर्ग में ओवरकोडिंग की आवश्यकता होती है, जिसके परिणामस्वरूप एक लेआउट पास का प्रदर्शन किया जाता है, हालांकि इस लेआउट पास के परिणामों को नजरअंदाज कर दिया जाता है और सिस्टम फ्रेम को टेबल व्यू और 0 की चौड़ाई पर सेट कर दिया जाता है।


3

निम्नलिखित ने मेरे लिए काम किया।

  1. UIViewहेडर व्यू के रूप में एक सादे पुराने का उपयोग करें ।
  2. उस में सबव्यू जोड़ें UIView
  3. सबवॉइल पर ऑटोलॉययट का उपयोग करें

मुख्य लाभ जो मैं देख रहा हूं वह है फ्रेम गणना। Apple को UITableViewइसे आसान बनाने के लिए वास्तव में API को अपडेट करना चाहिए ।

SnapKit का उपयोग करके उदाहरण:

let layoutView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 60))
layoutView.backgroundColor = tableView.backgroundColor
tableView.tableHeaderView = layoutView

let label = UILabel()
layoutView.addSubview(label)
label.text = "I'm the view you really care about"
label.snp_makeConstraints { make in
    make.edges.equalTo(EdgeInsets(top: 10, left: 15, bottom: -5, right: -15))
}

3

अजीब चीजें होती हैं। systemLayoutSizeFittingSize iOS9 के लिए बढ़िया काम करता है, लेकिन मेरे मामले में iOS 8 के लिए नहीं है। तो यह समस्या काफी आसान है। बस हेडर में नीचे के दृश्य के लिए लिंक प्राप्त करें और सुपर कॉल अपडेट हेडर व्यू सीमा के बाद DIDLayoutSubviews में CGRectGetMaxY (yourview.frame) + पैडिंग के रूप में ऊँचाई डालकर देखें।

UPD: अब तक का सबसे आसान उपाय : इसलिए, शीर्ष लेख में, सबव्यू देखें और इसे बाएँ , दाएँ , शीर्ष पर पिन करें । उस सबव्यू में अपने साक्षात्कारों को ऑटो-हाइट बाधाओं के साथ रखें। उसके बाद सभी नौकरी को ऑटोलाययट को दें (कोई गणना आवश्यक नहीं)

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGFloat height = CGRectGetMaxY(self.tableView.tableHeaderView.subviews.firstObject.frame);
    self.tableView.tableHeaderView.bounds = CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), height);
    self.tableView.tableHeaderView = self.tableView.tableHeaderView;
}

परिणामस्वरूप सबव्यू का विस्तार हो रहा है / जैसे सिकुड़ रहा है, अंत में यह viewDidLayoutSubviews को कॉल करता है। उस समय जब हम दृश्य के वास्तविक आकार को जानते हैं, इसलिए शीर्षलेख दृश्य ऊंचाई सेट करें और इसे पुनः असाइन करके अपडेट करें। एक जादू की तरह काम करता है!

पाद दृश्य के लिए भी काम करता है।


1
IOS 10. में मेरे लिए यह लूप है
सिमोन

3

स्विफ्ट 4.2 के लिए अपडेट किया गया

extension UITableView {

    var autolayoutTableViewHeader: UIView? {
        set {
            self.tableHeaderView = newValue
            guard let header = newValue else { return }
            header.setNeedsLayout()
            header.layoutIfNeeded()
            header.frame.size = 
            header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
            self.tableHeaderView = header
        }
        get {
            return self.tableHeaderView
        }
    }
}

2

हेडर और टेबलव्यू के बीच आप शीर्ष + क्षैतिज स्थान बाधा जोड़ सकते हैं, इसे सही ढंग से रखने के लिए (यदि हेडर में ही सभी आवश्यक आंतरिक लेआउट बाधाएं हैं, जिसमें एक सही फ्रेम है)

तालिका में व्यूकार्ट्रोल व्यूडीडलड विधि

    headerView.translatesAutoresizingMaskIntoConstraints = false

    tableView.tableHeaderView = headerView

    headerView.widthAnchor.constraint(equalTo: tableView.widthAnchor).isActive = true
    headerView.topAnchor.constraint(equalTo: tableView.topAnchor).isActive = true
    headerView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true

1

मेरा टेबल हेडर दृश्य एक यूइवीवाई सबक्लास है - मैंने इनीशियलाइज़र के भीतर एक एकल कंटेंट व्यू यूआईवाईईवाई बनाया है, इसकी सीमाएं टेबल हेडर व्यू के फ्रेम के समान हैं और मैंने अपनी सभी वस्तुओं को एक सबव्यू के रूप में जोड़ा है।

फिर अपने ऑब्जेक्ट्स के लिए बाधाओं को शुरुआती के layoutSubviewsबजाय टेबल हेडर व्यू की विधि में जोड़ें। जिससे दुर्घटना टल गई।

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:CGRectMake(0, 0, 0, 44.0)];
    if (self) {
        UIView *contentView = [[UIView alloc] initWithFrame:self.bounds];
        contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        // add other objects as subviews of content view

    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    // remake constraints here
}

1

मेरा AutoLayout बहुत अच्छा काम कर रहा है:

CGSize headerSize = [headerView systemLayoutSizeFittingSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), 0) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
headerView.frame = CGRectMake(0, 0, headerSize.width, headerSize.height);
self.tableView.tableHeaderView = headerView;

मैंने ऐसा बिल्कुल नहीं किया, लेकिन आपने मुझे एक अच्छा विचार दिया - शीर्ष लेख को हटाते हुए, इसके फ्रेम को फिर से सेट करना और इसे वापस जोड़ना।
दिनेशर्जनी

1

ज्यादातर मामलों के लिए सबसे अच्छा समाधान केवल रूपरेखा से लड़ना नहीं है और ऑटोरेस्पर्सिंग मास्क को गले लगाना है:

// embrace autoresizing masks and let the framework add the constraints for you
headerView.translatesAutoresizingMaskIntoConstraints = true
headerView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

// figure out what's the best size based on the table view width
let width = self.tableView.frame.width
let targetSize = headerView.systemLayoutSizeFitting(CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
headerView.frame.size = targetSize
self.tableView.tableHeaderView = headerView

ऑटोरेस्सिगिंग मास्क का उपयोग करके आप फ्रेमवर्क को बता रहे हैं कि जब पर्यवेक्षक अपना आकार बदलता है, तो आपके दृश्य का आकार कैसे बदलना चाहिए। लेकिन यह परिवर्तन आपके द्वारा निर्धारित प्रारंभिक फ्रेम पर आधारित है।


0

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन इस बारे में सभी एसओ पोस्टों के माध्यम से जाने और एक पूरी दोपहर को इसी के साथ खेलने के बाद, मैं आखिरकार एक साफ और बहुत सरल समाधान के साथ आया

सबसे पहले, मेरा विचार पदानुक्रम इस तरह दिखता है:

  1. टेबल व्यू
    1. राय tableHeaderView
      1. शीर्ष लेख के साथ देखें शीर्ष लेख

अब View (No.3) के अंदर, मैंने सभी बाधाओं को सेट कर दिया क्योंकि मैं सामान्य रूप से कंटेनर में नीचे की जगह शामिल करूंगा। यह कंटेनर (यानी 3. व्यू यानी हेडर व्यू) को अपने आकार के आधार पर बनाएगा, यह साक्षात्कार और उनकी कमी है।

उसके बाद, मैंने इनके बीच 3. Viewऔर बाधाओं को निर्धारित किया 2. View:

  1. कंटेनर के लिए शीर्ष स्थान: 0
  2. कंटेनर में अग्रणी स्थान: 0
  3. कंटेनर के लिए ट्रेलिंग स्पेस: 0

ध्यान दें कि मैं जानबूझकर नीचे की जगह जानबूझकर छोड़ देता हूं।

एक बार जब यह सब स्टोरीबोर्ड में हो जाता है, तो जो कुछ करना बाकी है, वह उन तीन पंक्तियों को चिपका देता है:

if (self.headerView.frame.size.height != self.tableView.tableHeaderView.frame.size.height) {
    UIView *header = self.tableView.tableHeaderView;
    CGRect frame = self.tableView.tableHeaderView.frame;
    frame.size.height = self.headerView.frame.size.height + frame.origin.y;
    header.frame = frame;
    self.tableView.tableHeaderView = header;
}

0

टिप्स: यदि आप विधि सेट का उपयोग करते हैं ।AndLayoutTableHeaderView, तो आपको साक्षात्कार के फ़्रेम को अपडेट करना चाहिए, इसलिए इस स्थिति में UILabel के पसंदीदामैक्सआउटआउट को कॉल किया जाना चाहिए, इससे पहले कि SystemLayoutSizeFittingSittingSearch नाम से कॉल करें, लेआउट में कॉल न करें।

कोड शो


0

मेरे दृष्टिकोण को साझा करें।

UITableView+XXXAdditions.m

- (void)xxx_setTableHeaderView:(UIView *)tableHeaderView layoutBlock:(void(^)(__kindof UIView *tableHeaderView, CGFloat *containerViewHeight))layoutBlock {
      CGFloat containerViewHeight = 0;
      UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
      [backgroundView addSubview:tableHeaderView];
      layoutBlock(tableHeaderView, &containerViewHeight);

      backgroundView.frame = CGRectMake(0, 0, 0, containerViewHeight);

      self.tableHeaderView = backgroundView;
}

उपयोग।

[self.tableView xxx_setTableHeaderView:myView layoutBlock:^(__kindof UIView * _Nonnull tableHeaderView, CGFloat *containerViewHeight) {
    *containerViewHeight = 170;

    [tableHeaderView mas_makeConstraints:^(MASConstraintMaker *make) {
      make.top.equalTo(@20);
      make.centerX.equalTo(@0);
      make.size.mas_equalTo(CGSizeMake(130, 130));
    }];
  }];

0

मेरे मामले में systemLayoutSizeFittingSize के साथ किसी कारण से काम नहीं किया। मेरे लिए जो काम किया गया वह हॉटजार्ड द्वारा पोस्ट किए गए समाधान का एक संशोधन है (वह मूल समाधान आईओएस 8 पर मेरे मामले में भी काम नहीं किया है)। मुझे क्या करने की आवश्यकता है हेडर दृश्य में एक सबव्यू जगह है और इसे बाएं, दाएं, शीर्ष (नीचे से पिन न करें) पर पिन करें। सबव्यूऑउट का उपयोग करके सब कुछ उस सबव्यू में रखें और कोड में यह करें:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self resizeHeaderToFitSubview];
}

- (void)resizeHeaderToFitSubview
{
    UIView *header = self.tableView.tableHeaderView;
    [header setNeedsLayout];
    [header layoutIfNeeded];
    CGFloat height = CGRectGetHeight(header.subviews.firstObject.bounds);
    header.bounds = CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), height);
    self.tableView.tableHeaderView = nil;
    self.tableView.tableHeaderView = header;
}

0

एक पुराना पद। लेकिन एक अच्छी पोस्ट। यहाँ मेरे 2 सेंट है।

सबसे पहले, सुनिश्चित करें कि आपके हेडर दृश्य में इसकी बाधाएं हैं ताकि यह समर्थन कर सके कि यह आंतरिक सामग्री का आकार है। फिर निम्नलिखित करें।

//ViewDidLoad
headerView.translatesAutoresizingMaskIntoConstraints = false
headerView.configure(title: "Some Text A")

//Somewhere else
headerView.update(title: "Some Text B)

private var widthConstrained = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if widthConstrained == false {
        widthConstrained = true
        tableView.addConstraint(NSLayoutConstraint(item: headerView, attribute: .width, relatedBy: .equal, toItem: tableView, attribute: .width, multiplier: 1, constant: 0))
        headerView.layoutIfNeeded()
        tableView.layoutIfNeeded()
    }
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { (context) in
        self.headerView.layoutIfNeeded()
        self.tableView.layoutIfNeeded()
    }, completion: nil)
}

0

मैं निम्नलिखित दृष्टिकोण से इसे प्राप्त करने में सक्षम था (यह उसी तरह पाद लेख के लिए काम करता है)।

सबसे पहले, आपको छोटे UITableViewविस्तार की आवश्यकता होगी :

स्विफ्ट 3

extension UITableView {
    fileprivate func adjustHeaderHeight() {
        if let header = self.tableHeaderView {
            adjustFrame(header)
        }
    }

    private func adjustFrame(_ view: UIView) {
        view.frame.size.height = calculatedViewHeight(view)
    }

    fileprivate func calculatedHeightForHeader() -> CGFloat {
        if let header = self.tableHeaderView {
            return calculatedViewHeight(header)
        }
        return 0.0
    }

    private func calculatedViewHeight(_ view: UIView) -> CGFloat {
        view.setNeedsLayout()
        let height = view.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        return height
    }
}

आपके विचार में नियंत्रक वर्ग कार्यान्वयन:

// this is a UIView subclass with autolayout
private var headerView = MyHeaderView()

override func loadView() {
    super.loadView()
    // ...
    self.tableView.tableHeaderView = headerView
    self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension
    // ...
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    // this is to prevent recursive layout calls
    let requiredHeaderHeight = self.tableView.calculatedHeightForHeader()
    if self.headerView.frame.height != requiredHeaderHeight {
        self.tableView.adjustHeaderHeight()
    }
}

शीर्ष लेख UIViewके सबव्यू कार्यान्वयन के बारे में नोट्स :

  1. आपको 100% यकीन है कि आपके हेडर दृश्य में सही ऑटोलैयट सेटअप है। मैं सरल हेडर दृश्य के साथ सिर्फ एक हींग बाधा के साथ शुरू करने और ऊपर सेटअप की कोशिश करने की सलाह दूंगा।

  2. ओवरराइड requiresConstraintBasedLayoutऔर वापसी true:

class MyHeaderView: UIView {
   // ...
   override static var requiresConstraintBasedLayout : Bool {
       return true
   }
   // ...
}

0

Xamarin उपयोगकर्ताओं के लिए:

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();

    TableviewHeader.SetNeedsLayout();
    TableviewHeader.LayoutIfNeeded();

    var height = TableviewHeader.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize).Height;
    var frame = TableviewHeader.Frame;
    frame.Height = height;
    TableviewHeader.Frame = frame;
}

मान लें कि आपने अपने टेबलव्यू के हेडर व्यू को टेबलव्यूहेडर नाम दिया है


0

यहां बताया गया है कि आप अपने काम को कैसे कर सकते हैं UIViewController

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if headerView.frame.size.height == 0 {
      headerView.label.preferredMaxLayoutWidth = view.bounds.size.width - 20
      let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height

      headerView.frame.size = CGSize(width: tableView.bounds.size.width, height: height)
    }
  }

0

कोई भी बाधा-आधारित UIViewएक अच्छा हो सकता है tableHeaderView

एक को सेट करने की जरूरत है tableFooterView पहले और फिर अतिरिक्त ट्रेलिंग बाधा को tableFooterViewऔर पर थोपना पड़ता है tableHeaderView

- (void)viewDidLoad {

    ........................
    // let self.headerView is some constraint-based UIView
    self.tableView.tableFooterView = [UIView new];
    [self.headerView layoutIfNeeded];
    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;
    [self.tableFooterView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor].active = YES;

}

सभी यहां सभी विवरण और कोड स्निपेट पा सकते हैं


0

मैंने एक समाधान निकाला है। एक खाली uiview आवरण में अपने ऑटोलैयट राइटेन एक्सिब हेडर दृश्य को लपेटें, और हैडर व्यू को टेबल व्यू के टेबल व्यूहेयर प्रॉपर्टी में असाइन करें।

    UIView *headerWrapper = [[UIView alloc] init];
    AXLHomeDriverHeaderView *headerView = [AXLHomeDriverHeaderView loadViewFromNib];
    [headerWrapper addSubview:headerView];
    [headerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(headerWrapper);
    }];
    self.tableView.tableHeaderView = headerView;

0

यहाँ IOS 12 में UITableViewController के लिए क्या काम करता है,

शीर्ष लेख के लिए सभी प्रोटोटाइप कोशिकाओं के ऊपर और पाद लेख के लिए सभी प्रोटोटाइप कोशिकाओं के नीचे तालिका दृश्य में एक UIView लपेटें। आवश्यकतानुसार अपना हेडर और फुटर सेट करें। सभी आवश्यक बाधाओं को निर्धारित करें।

अब निम्नलिखित विस्तार विधियों का उपयोग करें

public static class UITableVIewExtensions
{

    public static void MakeHeaderAutoDimension(this UITableView tableView)
    {
        if (tableView.TableHeaderView is UIView headerView) {
            var size = headerView.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize);
            if (headerView.Frame.Size.Height != size.Height) {
                var frame = headerView.Frame;
                frame.Height = size.Height;
                headerView.Frame = frame;
                tableView.TableHeaderView = headerView;
                tableView.LayoutIfNeeded();
            }
        }
    }

    public static void MakeFooterAutoDimension(this UITableView tableView)
    {
        if (tableView.TableFooterView is UIView footerView) {
            var size = footerView.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize);
            if (footerView.Frame.Size.Height != size.Height) {
                var frame = footerView.Frame;
                frame.Height = size.Height;
                footerView.Frame = frame;
                tableView.TableFooterView = footerView;
                tableView.LayoutIfNeeded();
            }
        }
    }
}

और इसे UDableViewController के उपवर्ग के ViewDidLayoutSubviews में कॉल करें

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();

    TableView.MakeHeaderAutoDimension();
    TableView.MakeFooterAutoDimension();
}

0

मुझे चौड़ाई 375pt होने की समस्या का सामना करना पड़ा, मेरे लिए काम करने का एकमात्र तरीका सही चौड़ाई प्राप्त करने के लिए टेबल व्यू को पुनः जारी करना है। फ़्रेम साइज़ सेट करने के लिए मैंने ऑटोलेयआउट को भी प्राथमिकता दी।

यहाँ वह संस्करण है जो मेरे लिए काम करता है:

Xamarin.iOS

public static void AutoLayoutTableHeaderView(this UITableView tableView, UIView header)
{
    tableView.TableHeaderView = header;
    tableView.SetNeedsLayout();
    tableView.LayoutIfNeeded();
    header.WidthAnchor.ConstraintEqualTo(tableView.Bounds.Width).Active = true;       
    tableView.TableHeaderView = header;
}

स्विफ्ट संस्करण (@ पैने उत्तर से संशोधित)

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        self.setNeedsLayout()
        self.layoutIfNeeded()
        header.widthAnchor.widthAnchor.constraint(equalTo: self.bounds.width).isActive = true
        self.tableHeaderView = header
    }
}


0

मेरा समाधान इस तरह एक नया वर्ग बना रहा है।

class BaseTableHeaderView: UIView {

    func sizeToFitBasedOnConstraints(width: CGFloat = Screen.width) {
        let size = systemLayoutSizeFitting(CGSize(width: width, height: 10000),
                                              withHorizontalFittingPriority: .required,
                                              verticalFittingPriority: .fittingSizeLevel)
        frame = CGRect(origin: .zero, size: size)
    }

    override func willMove(toSuperview newSuperview: UIView?) {
        sizeToFitBasedOnConstraints()
        super.willMove(toSuperview: newSuperview)
    }

}

इसका उपयोग करने के लिए, बस अपने सभी साक्षात्कारों को एक उदाहरण पर जोड़ें BaseTableHeaderViewऔर इसे अपनी तालिका दृश्य में संलग्न करें।

let tableHeaderView = BaseTableHeaderView()
tableHeaderView.addSubview(...)
tableView.tableHeaderView = tableHeaderView

यह स्वचालित रूप से अपनी बाधाओं के आधार पर आकार देगा।


-1

स्वीकृत उत्तर एकल अनुभाग वाली तालिकाओं के लिए एकमात्र उपयोगी है। मल्टी-सेक्शन के लिए UITableViewबस यह सुनिश्चित करें कि आपका हेडर इनहेरिट करता है UITableViewHeaderFooterViewऔर आप ठीक हो जाएंगे।

एक विकल्प के रूप में, बस अपने वर्तमान हेडर contentViewको एक में एम्बेड करें UITableViewHeaderFooterView। बिल्कुल UITableViewCellकाम की तरह ।


9
प्रश्न tableHeaderViewअनुभाग हेडर के बारे में नहीं है।
Rpranata
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.