在 Interface Builder 中设计 UITableView 的部分标题 [英] Design UITableView's section header in Interface Builder
问题描述
我有一个带有 UITableView
的 xib
文件,我想使用委托方法为该文件添加自定义部分标题视图 tableView:viewForHeaderInSection:
.有没有可能在 Interface Builder
中设计它,然后以编程方式更改它的一些子视图的属性?
I have a xib
file with a UITableView
for which I want to add a custom section header view using the delegate method tableView:viewForHeaderInSection:
. Is there any possibility to design it in Interface Builder
and then change some of it's subview's properties programmatically?
我的 UITableView
有更多的部分标题,所以在 Interface Builder
中创建一个 UIView
并返回它不起作用,因为我有复制它,但没有任何好的方法来做到这一点.存档和取消存档对 UIImage
s 不起作用,因此 UIImageView
s 会显示为空白.
My UITableView
has more section headers so creating one UIView
in Interface Builder
and returning it doesn't work, because I'd have to duplicate it, but there isn't any good method of doing it. Archiving and unarchiving it doesn't work for UIImage
s so UIImageView
s would show up blank.
此外,我不想以编程方式创建它们,因为它们太复杂,而且生成的代码难以阅读和维护.
Also, I don't want to create them programmatically because they are too complex and the resulting code would be hard to read and maintain.
编辑 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;
}
我希望它看起来像这样:
and I would want it to look something like this:
- (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;
}
Edit 2:我没有使用 Storyboard
,只是使用 .xib
文件.另外,我没有 UITableViewController
,只有一个 UIViewController
,我在其中添加了一个 UITableView
.
Edit 2: I'm not using a Storyboard
, just .xib
files. Also, I don't have an UITableViewController
, just an UIViewController
in which I added an UITableView
.
推荐答案
我终于用本教程,主要包括以下内容(适应我的例子):
I finally solved it using this tutorial, which, largely consists of the following (adapted to my example):
- 创建子类
UIView
的SectionHeaderView
类. - 创建
SectionHeaderView.xib
文件并将其File's Owner
的CustomClass
设置为SectionHeaderView
类. - 在
.m
文件中创建一个UIView
属性,例如:@property (strong, nonatomic) IBOutlet UIView *viewContent;
- 将
.xib
的View
连接到这个viewContent
出口. 添加如下所示的初始化方法:
- Create
SectionHeaderView
class that subclassesUIView
. - Create
SectionHeaderView.xib
file and set it'sFile's Owner
'sCustomClass
to theSectionHeaderView
class. - Create an
UIView
property in the.m
file like:@property (strong, nonatomic) IBOutlet UIView *viewContent;
- Connect the
.xib
'sView
to thisviewContent
outlet. Add an initializer method that looks like this:
+ (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;
}
然后,我在 .xib
文件中添加了一个 UILabel
并将其连接到 labelCategoryName
插座并实现了 setCategoryName:
方法如下:SectionHeaderView
类中的
Then, I added an UILabel
inside the .xib
file and connected it to the labelCategoryName
outlet and implemented the setCategoryName:
method inside the SectionHeaderView
class like this:
- (void)setCategoryName:(NSString *)categoryName {
self.labelCategoryName.text = categoryName;
}
然后我实现了这样的 tableView:viewForHeaderInSection:
方法:
I then implemented the tableView:viewForHeaderInSection:
method like this:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
SectionHeaderView *sectionHeaderView = [SectionHeaderView header];
[sectionHeaderView setCategoryName:self.categoriesNames[section]];
return sectionHeaderView;
}
它终于奏效了.每个部分都有自己的名称,而且 UIImageView
也能正确显示.
And it finally worked. Every section has it's own name, and also UIImageView
s show up properly.
希望它可以帮助像我一样在整个网络上一遍又一遍地发现相同错误解决方案的其他人.
Hope it helps others that stumble over the same wrong solutions over and over again, all over the web, like I did.
这篇关于在 Interface Builder 中设计 UITableView 的部分标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!