在Interface Builder中设计UITableView的节头

Iul*_*rei 27 iphone objective-c interface-builder uitableview ios

我有一个xib文件UITableView,我想使用委托方法添加自定义节标题视图tableView:viewForHeaderInSection:.有没有可能设计它Interface Builder,然后以编程方式更改它的一些子视图的属性?

UITableView有更多的章节标题,以便创建一个UIViewInterface Builder和返回这是行不通的,因为我不得不重复它,但没有做任何好的方法.归档和取消归档它不适用于UIImages所以UIImageViews会显示空白.

此外,我不想以编程方式创建它们,因为它们太复杂,结果代码很难读取和维护.

编辑1:这是我的tableView:viewForHeaderInSection:方法:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }

    CGSize headerSize = CGSizeMake(self.view.frame.size.width, 100);

    /* wrapper */

    UIView *wrapperView = [UIView viewWithSize:headerSize];

    wrapperView.backgroundColor = [UIColor colorWithHexString:@"2670ce"];

    /* title */

    CGPoint titleMargin = CGPointMake(15, 8);

    UILabel *titleLabel = [UILabel labelWithText:self.categoriesNames[section] andFrame:CGEasyRectMake(titleMargin, CGSizeMake(headerSize.width - titleMargin.x * 2, 20))];

    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.font = [UIFont fontWithStyle:FontStyleRegular andSize:14];

    [wrapperView addSubview:titleLabel];

    /* body wrapper */

    CGPoint bodyWrapperMargin = CGPointMake(10, 8);

    CGPoint bodyWrapperViewOrigin = CGPointMake(bodyWrapperMargin.x, CGRectGetMaxY(titleLabel.frame) + bodyWrapperMargin.y);
    CGSize bodyWrapperViewSize = CGSizeMake(headerSize.width - bodyWrapperMargin.x * 2, headerSize.height - bodyWrapperViewOrigin.y - bodyWrapperMargin.y);

    UIView *bodyWrapperView = [UIView viewWithFrame:CGEasyRectMake(bodyWrapperViewOrigin, bodyWrapperViewSize)];

    [wrapperView addSubview:bodyWrapperView];

    /* image */

    NSInteger imageSize = 56;
    NSString *imageName = [self getCategoryResourceItem:section + 1][@"image"];

    UIImageView *imageView = [UIImageView imageViewWithImage:[UIImage imageNamed:imageName] andFrame:CGEasyRectMake(CGPointZero, CGEqualSizeMake(imageSize))];

    imageView.layer.masksToBounds = YES;
    imageView.layer.cornerRadius = imageSize / 2;

    [bodyWrapperView addSubview:imageView];

    /* labels */

    NSInteger labelsWidth = 60;

    UILabel *firstLabel = [UILabel labelWithText:@"first" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 0, labelsWidth, 16)];

    [bodyWrapperView addSubview:firstLabel];

    UILabel *secondLabel = [UILabel labelWithText:@"second" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 20, labelsWidth, 16)];

    [bodyWrapperView addSubview:secondLabel];

    UILabel *thirdLabel = [UILabel labelWithText:@"third" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 40, labelsWidth, 16)];

    [bodyWrapperView addSubview:thirdLabel];

    [@[ firstLabel, secondLabel, thirdLabel ] forEachView:^(UIView *view) {
        UILabel *label = (UILabel *)view;

        label.textColor = [UIColor whiteColor];
        label.font = [UIFont fontWithStyle:FontStyleLight andSize:11];
    }];

    /* line */

    UIView *lineView = [UIView viewWithFrame:CGRectMake(imageSize + labelsWidth + bodyWrapperMargin.x * 2, bodyWrapperMargin.y, 1, bodyWrapperView.frame.size.height - bodyWrapperMargin.y * 2)];

    lineView.backgroundColor = [UIColor whiteColorWithAlpha:0.2];

    [bodyWrapperView addSubview:lineView];

    /* progress */

    CGPoint progressSliderOrigin = CGPointMake(imageSize + labelsWidth + bodyWrapperMargin.x * 3 + 1, bodyWrapperView.frame.size.height / 2 - 15);
    CGSize progressSliderSize = CGSizeMake(bodyWrapperViewSize.width - bodyWrapperMargin.x - progressSliderOrigin.x, 30);

    UISlider *progressSlider = [UISlider viewWithFrame:CGEasyRectMake(progressSliderOrigin, progressSliderSize)];

    progressSlider.value = [self getCategoryProgress];

    [bodyWrapperView addSubview:progressSlider];

    return wrapperView;
}
Run Code Online (Sandbox Code Playgroud)

我希望它看起来像这样:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }

    SectionView *sectionView = ... // get the view that is already designed in the Interface Builder

    sectionView.headerText = self.categoriesNames[section];
    sectionView.headerImage = [self getCategoryResourceItem:section + 1][@"image"];

    sectionView.firstLabelText = @"first";
    sectionView.secondLabelText = @"second";
    sectionView.thirdLabelText = @"third";

    sectionView.progress = [self getCategoryProgress];

    return wrapperView;
}
Run Code Online (Sandbox Code Playgroud)

编辑2:我没有使用Storyboard,只是.xib文件.另外,我没有UITableViewController,只是UIViewController我添加了一个UITableView.

Swi*_*ect 81

故事板或XIB

  1. 相同Storyboard:

    return tableView.dequeueReusableCell(withIdentifier: "header")
    
    Run Code Online (Sandbox Code Playgroud)

    两节标题

  2. 单独XIB(附加步骤:您必须先注册Nib):

    tableView.register(UINib(nibName: "XIBSectionHeader", bundle:nil),
                       forCellReuseIdentifier: "xibheader")
    
    Run Code Online (Sandbox Code Playgroud)

要从a Storyboard而不是a 加载XIB,请参阅此Stack Overflow应答.


使用UITableViewCell在IB中创建Section Header

利用节标题是常规的这一事实,UIView也就是说UITableViewCell,a UIView.在Interface Builder中,将表视图单元格对象库拖放到表视图原型内容上.

标识符添加到新添加的表视图单元格中,并根据需要自定义其外观.对于这个例子,我用过header.

编辑单元格

使用dequeueReusableCell:withIdentifier找到您的节头,就像你的任何表格视图单元格.您需要提供heightForHeaderInSection,为清晰起见,硬编码为44:

//MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
    // This is where you would change section header content
    return tableView.dequeueReusableCell(withIdentifier: "header")
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
    return 44
}
Run Code Online (Sandbox Code Playgroud)

Swift 2及更早版本:

return tableView.dequeueReusableCellWithIdentifier("header") as? UIView
self.tableView.registerNib(UINib(nibName: "XIBSectionHeader", bundle:nil),
    forCellReuseIdentifier: "xibheader")
Run Code Online (Sandbox Code Playgroud)

►在GitHub上找到此解决方案以及有关Swift Recipes的其他详细信息.

  • "与故事板混合不好"对于使用完全不合适的方法来查看页眉和页脚视图是一个糟糕的借口.绝对应该使用`dequeueReusableHeaderFooterView()`; @FrederikA.Winkelsdorf是对的 (4认同)
  • 我认为现在已经改变了.使用tableView.dequeueReusableCellWithIdentifier("header")?.contentView.施放到UIView将永远失败. (3认同)
  • @SwiftArchitect没有使用适当方法的任何理由?应该使用`dequeueReusableHeaderFooterView()`而不是`dequeueReusableCellWithIdentifier`. (3认同)
  • 它就像在`UITableViewController -viewDidLoad()`中添加`self.tableView.registerNib(UINib(nibName: "XIBSectionHeader", bundle:nil), forCellReuseIdentifier: "xibheader")`一样简单。 (2认同)
  • 在使用这种方式之前,请检查此答案.因为布局/触摸处理会遇到问题,并且会重复使用这些剖面视图.http://stackoverflow.com/questions/9219234/how-to-implement-custom-table-view-section-headers-and-footers-with-storyboard (2认同)

Iul*_*rei 11

我终于使用本教程解决了它,它主要由以下内容组成(适用于我的示例):

  1. 创建SectionHeaderView子类的类UIView.
  2. 创建SectionHeaderView.xib文件,并设置它File's OwnerCustomClassSectionHeaderView类.
  3. UIView.m文件中创建一个属性,如:@property (strong, nonatomic) IBOutlet UIView *viewContent;
  4. 在连接.xibView这个viewContent插座.
  5. 添加如下所示的初始化方法:

    + (instancetype)header {
    
        SectionHeaderView *sectionHeaderView = [[SectionHeaderView alloc] init];
    
        if (sectionHeaderView) { // important part
            sectionHeaderView.viewContent = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:sectionHeaderView options:nil] firstObject];
    
            [sectionHeaderView addSubview:sectionHeaderView.viewContent];
    
            return sectionHeaderView;
        }
    
        return nil;
    }
    
    Run Code Online (Sandbox Code Playgroud)

然后,我UILabel.xib文件中添加了一个并将其连接到labelCategoryName插座并setCategoryName:SectionHeaderView类中实现了这样的方法:

- (void)setCategoryName:(NSString *)categoryName {

    self.labelCategoryName.text = categoryName;
}
Run Code Online (Sandbox Code Playgroud)

然后我实现了tableView:viewForHeaderInSection:这样的方法:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    SectionHeaderView *sectionHeaderView = [SectionHeaderView header];

    [sectionHeaderView setCategoryName:self.categoriesNames[section]];

    return sectionHeaderView;
}
Run Code Online (Sandbox Code Playgroud)

它终于奏效了.每个部分都有自己的名字,也UIImageView可以正确显示.

希望它可以帮助其他人一遍又一遍地绊倒相同的错误解决方案,就像我一样.


归档时间:

查看次数:

43572 次

最近记录:

8 年,2 月 前