2015-05-01 15 views
5

Tôi đang tải một tập tin tùy chỉnh XIB UIView như một cái nhìn tiêu đề của một UITableView bên trong một bộ điều khiển xem.Tableheader vấn đề xem autolayout

Chủ sở hữu tệp cho file xib là viewController. Tôi có cả & giao diện của viewController của UIView tuyên bố bên trong UIViewController.

ViewController.h

 @class ZeroStateView; 

     @interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> 

     @property (nonatomic, weak) IBOutlet CustomUITableView *tableView; 
     @property (nonatomic,strong) NSMutableArray *dataArray; 
     @property (weak, nonatomic) IBOutlet ZeroStateView *zeroStateView; 


     @end 


    @interface ZeroStateView : UIView 
    @property (weak, nonatomic) IBOutlet AutoLayoutLabel *titleLabel; 
    @property (weak, nonatomic) IBOutlet UIImageView *titleIcon; 

    - (void)updateView; 

    @end 

ViewController.m

- (void)prepareHeaderViewForZeroState{ 
      ZeroStateView *sizingView = [ZeroStateView new]; 
      [[[NSBundle mainBundle] loadNibNamed:@"ZeroStateView" owner:self options:nil] objectAtIndex:0]; 
      sizingView = self.zeroStateView; 
      [sizingView updateView]; 

      self.tableView.tableHeaderView = sizingView; 

      UIView *headerView = self.tableView.tableHeaderView; 



      CGFloat height = [headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; 

     CGRect headerFrame = headerView.frame; 
     headerFrame.size.height = height; 
     headerView.frame = headerFrame; 


     self.tableView.tableHeaderView = headerView; 
    } 

    @end 

    @implementation ZeroStateView 

    -(void)updateView{ 
     self.titleIcon.alpha = 0.5; 

     UIFontDescriptor *titleFontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; 

     self.titleLabel.text = @"This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. This is a long text message and its really long. "; 

    } 

Lớp AutolayoutLabel các phương pháp sau đây ghi đè:

- (void)setBounds:(CGRect)bounds { 
     [super setBounds:bounds]; 

     // For multiline label, preferredMaxLayoutWidth always matches the frame width 
     if (self.numberOfLines == 0 && bounds.size.width != self.preferredMaxLayoutWidth) { 
      self.preferredMaxLayoutWidth = self.bounds.size.width; 
      [self setNeedsUpdateConstraints]; 
     } 
    } 

Chiều cao tính theo systemLayoutSizeFittingSize: UILayoutFittingCompressedSize lợi nhuận 0. Như một kết quả tôi nhận được quan điểm sau khi xem bảng tiêu đề: Header view with height 0

Khi tôi thêm chiều cao thực tế như dưới đây, các tràn UILabel. Tôi đang mong uiview phát triển khi chiều cao nhãn tăng lên.

headerFrame.size.height = self.sizingView.frame.size.height; 

TableHeaderView not being resized properly

Dưới đây là ảnh chụp màn hình về điều đó hạn chế UIViews:

ZeroState view XIB file with constraints

làm tôi nhớ gì ở đây? Ai đó có thể chỉ cho tôi không?

Cập nhật Tôi đã tạo mẫu project để các bạn kiểm tra chính xác vấn đề là gì.

+0

Đối với những gì đáng giá, nó luôn giúp nêu rõ câu hỏi của bạn trong câu đầu tiên. –

+0

Bạn không nên gọi đây là 'ZeroStateView * sizingView = [ZeroStateView new];' nếu bạn gán thứ gì đó khác cho nó 2 dòng sau. – pteofil

+0

Khi nào bạn gọi 'prepareHeaderViewForZeroState'? – pteofil

Trả lời

2

Tôi đã thực hiện lại những gì bạn đã có cho đến nay theo một cách khác. Để bắt đầu, tôi đã xóa UIView trong ZeroStateView.xib rằng UIImageViewUILabel được nhúng. Cơ sở của xib đã là UIView, vì vậy không cần thiết phải thêm một số khác UIView vào đó.

Tiếp theo, tôi đã thay đổi các ràng buộc xung quanh.Tôi không nhớ chính xác những gì khó khăn tôi đã thay đổi, vì vậy tôi sẽ chỉ liệt kê chúng ra đây:

  1. ràng buộc cho UIImageView
    • Align Center X để SuperView
    • Width = 60
    • Height = 56
    • Space Top SuperView = 37
    • dưới Space để UILabel = 31
  2. ràng buộc cho UILabel
    • Left Space để SuperView = 15
    • Space Quyền SuperView = 15
    • Space dưới để SuperView = 45
    • Space Top UIImageView = 31

Vào mã. Trong ViewController.h, các IBOutlet đã không làm bất cứ điều gì như xa như tôi có thể nói, vì vậy tôi đã thay đổi mà tài sản để đọc @property (strong, nonatomic) ZeroStateView *zeroStateView;

Bây giờ thay đổi quan trọng: ViewController.m. Có hai phương pháp UITableViewDelegate sẽ thay thế prepareHeaderViewForZeroState. Trong viewDidLoad, khởi tạo zeroStateView và đặt đại biểu của chế độ xem bảng thành self.

- (void)viewDidLoad 
{ 
    //... 

    // Load the view 
    self.zeroStateView = [[[NSBundle mainBundle] loadNibNamed:@"ZeroStateView" owner:self options:nil] firstObject]; 
    [self.zeroStateView updateView]; 
    self.zeroStateView.backgroundColor = [UIColor darkGrayColor]; 

    // Set self for table view delegate for -heightForHeaderInSection: and viewForHeaderInSection: 
    self.dataTable.delegate = self; 
} 

Bây giờ chúng tôi là xem bảng của đại biểu, chúng tôi nhận được hai cuộc gọi phương pháp này sẽ cho phép chúng ta tùy biến xem tiêu đề và thiết lập chiều cao của mình một cách thích hợp.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    // This will set the header view to the zero state view we made in viewDidLoad 
    return self.zeroStateView; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    // sizeToFit describes the size that the label can fit itself into. 
    // So we are saying that the label can use the width of the view and infinite height. 
    CGSize sizeToFit = CGSizeMake(self.view.frame.size.width, MAXFLOAT); 

    // Then we ask the label to tell us how it can fit in that size. 
    // The label will respond with the width of the view and however much height it needs 
    // to display its text. This is the magic of how it grows vertically. 
    CGSize size = [self.zeroStateView.titleLabel sizeThatFits:sizeToFit]; 

    // Add the height the label needs to the overall zero state view. This should be changed 
    // to the height of the UIImage + the height we just got + the whitespace above and below 
    // each of these views. You can handle that part. 
    return self.zeroStateView.frame.size.height + size.height; 
} 

Tôi đã tải các thay đổi của mình lên Dropbox here.

0

Tôi không chắc nhưng bạn có thể kiểm tra xem bạn có một hàng đầu, đuôi, trở ngại trên và dưới cho cả UIImage và nhãn với tham chiếu đến các SuperView.

Edit: Thêm các hạn chế chiều rộng trước khi nhận được systemLayoutSize

NSLayoutConstraint *tempWidthConstraint = 
[NSLayoutConstraint constraintWithItem:self.contentView 
          attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual 
           toItem:nil 
          attribute:NSLayoutAttributeNotAnAttribute 
          multiplier:1.0 
           constant:CGRectGetWidth(window.frame)]; 

widthConstraint.constant = tempWidthConstraint.constant; 
[self.contentView addConstraint:tempWidthConstraint]; 

CGSize fittingSize = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 
CGFloat height = fittingSize.height +1; 
[self.contentView removeConstraint:tempWidthConstraint]; 
+0

Ngoài ra thêm một hàng đầu, trailing, hạn chế hàng đầu cho xem hình ảnh biểu tượng cảnh báo. –

+0

tôi muốn số lần xem hình ảnh được căn giữa. Nếu tôi đặt dấu cách, biểu tượng số lần xem sẽ biến mất khỏi chế độ xem –

+0

vâng ok, bạn đã thử thêm ràng buộc chiều rộng cho chế độ xem trước khi nhận systemLayoutSize, sau đó chỉ xóa ràng buộc chiều rộng –

1

Chỉ cần thay đổi kích thước của khung của tableHeaderView, không thay đổi kích thước của nó. Bạn phải đặt lại bảng tableView để buộc tải lại.

Bạn phải gọi này một lần nữa self.tableView.tableHeaderView = headerView; sau khi thiết lập kích thước khung hình mới.

+0

nhưng systemLayoutSizeFittingSize trả về số không –

+0

Bất kỳ vấn đề nào khác mà bạn có , bạn _must_ đặt self.tableView.tableHeaderView = headerView; thay đổi một lần nữa hoặc chiều cao trong chế độ xem tiêu đề sẽ không có hiệu lực trên chế độ xem bảng. Xem xét nó một lỗi trong iOS (tôi làm), nhưng bạn cần phải làm điều đó. – gnasher729

1

Như bạn gọi prepareHeaderViewForZeroState phương pháp từ viewwillappear. Tại thời điểm đó bạn bố trí không được tính toán. do đó bố trí lực để tính toán trước khi gọi phương thức systemLayoutSizeFittingSize để tính chiều cao của ô. Đây là mã mà bạn cần viết trước khi gọi systemLayoutSizeFittingSize.

UIView *header = self.tableView.tableHeaderView; 

    [header setNeedsLayout]; 
    [header layoutIfNeeded]; 

Edit:

Bạn chỉ cần để lại 1 trở ngại trong ZeroStateView.xib. đó là Bottom Space to : Superview. vui lòng tham khảo ảnh chụp màn hình.

enter image description here

Output:

enter image description here

Ở đây bạn có Updated code

Hy vọng điều này giúp bạn.

+0

Tôi đã cập nhật mã của mình để thêm vào những gì bạn đề xuất nhưng điều đó không làm được gì nhiều. Tôi đã cập nhật dự án mẫu.bạn có thể chơi với nó khi bạn có thể. –

0

Có một vài điều ở đây gây nhầm lẫn cho tôi có thể làm phức tạp mọi thứ.

  1. Tại sao bạn lại phân loại nhãn?
  2. Các ràng buộc không thực sự hợp lý.
    • Tại sao nhãn có hai giới hạn chiều cao, hằng số và ràng buộc?? Loại bỏ cả hai, bạn không cần một trong hai.
    • Ngoài ra, không gian dọc của bạn ở dưới cùng của vùng chứa cũng là ≥. Tại sao? Khi nó đứng, chế độ xem tùy chỉnh của bạn không có chiều cao được xác định, đó có thể là lý do tại sao kích thước phù hợp trả về độ cao bằng không.

Một khi bạn giải quyết những vấn đề này, cho tôi biết nếu bạn có may mắn hơn.

+0

Xin cảm ơn vì đã chỉ ra những sai lầm. Tôi cập nhật mã của tôi và điều đó không làm được gì nhiều. Tôi đã cập nhật dự án mẫu. bạn có thể chơi với nó khi bạn có thể. –

Các vấn đề liên quan