您如何显示分组表部分的行分隔符?

Posted

技术标签:

【中文标题】您如何显示分组表部分的行分隔符?【英文标题】:How do you show line dividers for grouped table sections? 【发布时间】:2014-08-07 19:11:49 【问题描述】:

我想模仿标准联系人应用程序的分组表(左)。每个部分的上方和下方都有灰线分隔线。在我的分组表(右)中,每个部分上方没有一行。更奇怪的是,中间部分根本没有线条。

#import "GroupViewController.h"
#import "UserCollectionViewCell.h"
#import "UIView+position.h"
#import "UIColor+style.h"
#import "UserPublicViewController.h"
#import "RecipientsGroupsModel.h"

static NSString* AVATAR_CELL_ID = @"groupUserCollectionUserView";
static const CGFloat AVATAR_ITEM_SPACING = 16.0;
static const CGFloat AVATAR_LINE_SPACING = 9.0;
static const CGFloat AVATAR_MARGIN = 15.5;
static const CGFloat AVATAR_CELL_WIDTH = 45.0;
static const CGFloat AVATAR_CELL_HEIGHT = 58.0;

typedef enum 
    GroupViewControllerTableSectionTitle,
    GroupViewControllerTableSectionUsers,
    GroupViewControllerTableSectionDelete
 GroupViewControllerTableSection;

@interface GroupViewController ()

@property(nonatomic, strong) Group* group;
@property(nonatomic, strong) UICollectionView* avatarCollectionView;
@property(nonatomic, readonly) CGFloat usersHeight;

- (void)didLongTapAvatars:(UILongPressGestureRecognizer*)gesture;

@end

@implementation GroupViewController

#pragma mark UIViewController

- (NSString*)title

    return @"Group";


- (void)loadView

    [super loadView];
    self.view.backgroundColor = [UIColor backgroundColor];


- (void)viewDidLoad

    [super viewDidLoad];

    self.navigationItem.rightBarButtonItem = self.editButtonItem;


- (void)setEditing:(BOOL)editing animated:(BOOL)animated

    [super setEditing:editing animated:animated];
    [self.tableView reloadData];
    [self.avatarCollectionView reloadData];


#pragma mark GroupViewController ()

- (void)didLongTapAvatars:(UILongPressGestureRecognizer *)gesture

    if (gesture.state == UIGestureRecognizerStateBegan) 
        [self setEditing:!self.isEditing animated:YES];
    


- (CGFloat)usersHeight

    return ceilf(
        self.group.users.count
        / floorf(
            (
                self.view.width
                - 2 * AVATAR_MARGIN
                + AVATAR_ITEM_SPACING
            )
            / (
                AVATAR_ITEM_SPACING
                + AVATAR_CELL_WIDTH
            )
        )
    )
    * (AVATAR_CELL_HEIGHT + AVATAR_LINE_SPACING)
    + AVATAR_LINE_SPACING;


#pragma mark GroupViewController

- (instancetype)initWithGroup:(Group *)group

    if (self = [super init]) 
        self.group = group;
    
    return self;


#pragma mark UITableViewDelegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    switch (indexPath.section) 
        case GroupViewControllerTableSectionTitle:
        case GroupViewControllerTableSectionDelete:
            return 44.0f;
            break;
        case GroupViewControllerTableSectionUsers:
            return self.usersHeight;
            break;
        default:
            return 0.0f;
    


- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

    return 22.0f;


- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

    switch (section) 
        case GroupViewControllerTableSectionDelete:
            return 22.0f;
            break;
        default:
            return 0.0f;
    


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

    // ios 7 applies a transclucent view if you don't return your own view
    return [[UIView alloc] init];


- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

    return [[UIView alloc] init];


#pragma mark UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    if (self.isEditing) 
        return GroupViewControllerTableSectionDelete + 1;
     else 
        return GroupViewControllerTableSectionUsers + 1;
    


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return 1;


- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    NSString* identifier = [NSNumber numberWithInteger:indexPath.section].stringValue;
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        switch (indexPath.section) 
            case GroupViewControllerTableSectionTitle:
                cell.textLabel.text = self.group.title;
                break;
            case GroupViewControllerTableSectionUsers: 
                if (self.avatarCollectionView == nil) 
                    UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc] init];
                    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
                    layout.sectionInset = UIEdgeInsetsMake(
                        AVATAR_LINE_SPACING,
                        AVATAR_MARGIN,
                        AVATAR_LINE_SPACING,
                        AVATAR_MARGIN
                    );
                    layout.itemSize = CGSizeMake(AVATAR_CELL_WIDTH, AVATAR_CELL_HEIGHT);
                    layout.minimumInteritemSpacing = AVATAR_ITEM_SPACING;
                    layout.minimumLineSpacing = AVATAR_LINE_SPACING;

                    self.avatarCollectionView = [[UICollectionView alloc]
                        initWithFrame:CGRectMake(
                            0.0,
                            0.0,
                            self.view.width,
                            self.usersHeight
                        )
                        collectionViewLayout:layout
                    ];
                    self.avatarCollectionView.backgroundColor = [UIColor clearColor];
                    self.avatarCollectionView.dataSource = self;
                    self.avatarCollectionView.delegate = self;
                    [self.avatarCollectionView registerClass:[UserCollectionViewCell class] forCellWithReuseIdentifier:AVATAR_CELL_ID];
                    [self.avatarCollectionView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongTapAvatars:)]];
                
                [cell.contentView addSubview:self.avatarCollectionView];
                break;
            
            case GroupViewControllerTableSectionDelete:
                cell.textLabel.text = @"Delete Group";
                cell.textLabel.textColor = [UIColor redColor];
                break;
        
    
    return cell;


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

    return NO;


#pragma mark UICollectionViewDataSource

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    UserCollectionViewCell* cell;
    cell = [self.avatarCollectionView dequeueReusableCellWithReuseIdentifier:AVATAR_CELL_ID forIndexPath:indexPath];
    cell.user = [self.group.users objectAtIndex:indexPath.row];
    cell.isEditing = self.isEditing;
    return cell;


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

    return self.group.users.count;


- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

    return 1;


#pragma mark UICollectionViewDelegate

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

    User* user = [self.group.users objectAtIndex:indexPath.row];

    if (self.isEditing) 
        if (self.group.users.count <= 1) 
            [RecipientsGroupsModel removeGroup:self.group];
            [self.navigationController popViewControllerAnimated:YES];
         else 
            [self.group.users removeObject:user];
            [RecipientsGroupsModel updateGroup:self.group];
            [self.avatarCollectionView deleteItemsAtIndexPaths:@[indexPath]];
        
     else 
        [self.navigationController pushViewController:[[UserPublicViewController alloc] initWithUser:user] animated:YES];
    


@end

【问题讨论】:

【参考方案1】:

您可以使用 UITableViewDelegate 方法:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

您可以在其中为任何部分的页眉和页脚指定所需的任何高度。如果您不需要页眉或页脚,则返回 0。

然后使用其他两种方法:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

在它们中,您可以编写自定义代码以使它们看起来像您想要的那样:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];

view.backgroundColor = [UIColor grayColor];

// ...
// Other customizations, like adding the gray line, etc.
// ...

return view;

【讨论】:

以上是关于您如何显示分组表部分的行分隔符?的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView的行项目视图隐藏/显示在Recyclerview的滚动上搞砸了

MySQL - 如何选择表中的行,其中 id 值位于另一个表中的逗号分隔字段中?

如何找到文件的行分隔符?

Flutter & Dart:用数字分组显示大数字

查询按日期范围分隔的行数

在 SQL 中将分隔的行拆分为列