如何向UITableViewCell添加自定义分隔符?

12

请耐心一些,因为这是一个较长的解释。

我有一个UIViewController,其中包含一个UIButton和一个UITableView,它加载不同类型的带有标识符Cell1Cell2UITableViewCell。当点击按钮上的事件touchUpInside时,会根据单元格标识符交换tableViewCell。我使用故事板。

两种单元格的分隔符都进行了自定义。

Cell1具有占据整个单元格底部、高度为1像素的分隔符。

Cell2的分隔线距离单元格左右各偏移了5像素。

每次单击tableView外部的按钮时,tableViewCell根据单元格标识符被交换。

最初,tableView占据viewController的全部宽度,并包含Cell1,但在点击按钮后,tableViewCell被更改为Cell2,并且tableView的框架被更改。宽度减小10,x-origin增加5。

但是当这种情况发生时,Cell2的分隔符距离右侧单元格有5像素的偏移量,但在左侧则有5像素的偏移。

对于加载有数据的所有Cell2,都会出现这种情况,而没有数据的单元格则会适当更改框架。但是接下来的单元格具有较大的宽度Cell1

-(void)setSeperatorStyleForTableView :(UITableViewCell *)cell //this is called in cellForRowAtIndex 
{
   //cell- type of cell(Cell1 or Cell2)

     CGRect seperatorFrame;
    UIImageView *seperatorImage;

    seperatorFrame = [self setSeperatorFrame:cell];

    if(firstCellToBeLoaded)//BOOL used to change the button text and load appropriate cells
    {
        seperatorImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"table_row         
                                                                            2.png"]];
    }
    else
    {

        seperatorImage = [[UIImageView alloc] initWithImage:[UIImage   
                                                  imageNamed:@"table_row.png"]];
    }
    seperatorImage.frame = seperatorFrame;
    seperatorImage.autoresizingMask = YES;
    [cell.contentView addSubview:seperatorImage];

}

//set the customized separator frame

-(CGRect)setSeperatorFrame :(UITableViewCell *)cell
{

    CGRect seperatorFrame;
    seperatorFrame.size.height = 1.0;
    seperatorFrame.origin.y = cell.frame.origin.y + (cell.frame.size.height - 1.0);

    if(firstCellToBeLoaded)
    {
        seperatorFrame.origin.x = cell.frame.origin.x ;
        seperatorFrame.size.width = cell.frame.size.width;
    }
    else
    {
        seperatorFrame.origin.x = cell.frame.origin.x + 5.0;
        seperatorFrame.size.width = cell.frame.size.width -10.0;

    }

    return seperatorFrame;
}
4个回答

45

您可以添加 tableView 的标准分隔线,并在每个单元格的顶部添加自定义线条。

在以下代码中更改 UIView高度/宽度/颜色/图像 以设置您的分隔线。

添加自定义分隔线最简单的方法是添加一个高度为1像素的简单 UIView

UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1)];/// change size as you need.
separatorLineView.backgroundColor = [UIColor grayColor];// you can also put image here
[cell.contentView addSubview:separatorLineView];

这段代码可能会解决你的问题 :)


1
一般来说,这个方法是有效的。但是当单元格被选中/高亮时,它会出现问题,因为此时所有子视图中的 backgroundColor 都会被重置为透明。因此,最好创建一个简单的 UIView 子类,在 drawRect: 中用给定的颜色填充自身,而不是使用 backgroundColor。另外,分隔线不能放在 contentView 中(因为删除按钮、辅助视图等),必须直接放在单元格中。 - Sulthan
@Sulthan - 你也可以放置图片而不是颜色,我在评论中也提到了这个问题 :) 谢谢 :) - iPatel
1
最后一个单元格没有添加一行。 - Mittchel
@Mittchel - 如果你想覆盖最后一个单元格分隔线,那么需要将separatorLineView的Y轴从0改为cell.height-1。 - Govaadiyo

2

正确的做法应该是将分隔符放在单元格类中。如果您还没有在子类UITableViewCell中添加分隔符图像变量,则可以在每个单元格创建时只更改图像和框架,而不是在每次重绘时都添加它。如果您需要这方面的代码,我也可以提供。当前,当单元格被重新绘制时,它已经具有了您上次添加的图像,并且您只需再次添加即可。要么您在-prepareForReuse方法中删除它,要么按照我上面的说明进行操作。

***** Custom Cell *****
//
//  CustomCell.m
//  Custom
//
//  Created by Syed Arsalan Pervez on 2/8/13.
//  Copyright (c) 2013 SAPLogix. All rights reserved.
//

#import "CustomCell.h"

@implementation CustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        _separatorImage = [[UIImageView alloc] initWithFrame:CGRectZero];
        [[self contentView] addSubview:_separatorImage];
    }
    return self;
}

- (void)prepareForReuse
{
    _separatorImage.image = nil;
}

- (void)dealloc
{
    [_separatorImage release];
    [super dealloc];
}

@end

在视图控制器中使用上述单元格。

***** Test View Controller *****
//
//  TestViewController.m
//  Custom
//
//  Created by Syed Arsalan Pervez on 2/8/13.
//  Copyright (c) 2013 SAPLogix. All rights reserved.
//

#import "TestViewController.h"
#import "CustomCell.h"

@interface TestViewController ()

@end

@implementation TestViewController

- (void)viewDidLoad
{
    [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];

#warning TODO: set the image name here
    _separatorImage1 = [[UIImage imageNamed:@""] retain];
    _separatorImage2 = [[UIImage imageNamed:@""] retain];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *_identifier = @"CustomCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:_identifier];
    if (!cell)
    {
        cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:_identifier] autorelease];
    }

    //Set Separator Image Here
    //Preload the image so it doesn't effect the scrolling performance
    CGRect frame = cell.contentView.frame;
    switch (indexPath.row)
    {
        case 0:
            cell.separatorImage.image = _separatorImage1;
            cell.separatorImage.frame = CGRectMake(0, CGRectGetMaxY(frame)-1, frame.size.width, 1);
            break;
        case 1:
            cell.separatorImage.image = _separatorImage2;
            cell.separatorImage.frame = CGRectMake(frame.origin.x+5, CGRectGetMaxY(frame)-1, frame.size.width-10, 1);
            break;
    }

    return cell;
}

- (void)dealloc
{
    [_separatorImage1 release];
    [_separatorImage2 release];

    [super dealloc];
}

@end

1
我是这样做的...希望能帮到你。
//
//  UITableViewCell+MyAdditions.h
//
//  Created by Roberto O. Buratti on 19/02/14.
//

#import <UIKit/UIKit.h>

@interface UITableViewCell (MyAdditions)

@property (nonatomic,assign) UITableViewCellSeparatorStyle cellSeparatorStyle;
@property (nonatomic,strong) UIColor *cellSeparatorColor;

@end

//
//  UITableViewCell+MyAdditions.m
//
//  Created by Roberto O. Buratti on 19/02/14.
//

#import "UITableViewCell+MyAdditions.h"

NSString *const kUITablewViewCellSeparatorLayerName = @"kUITablewViewCellSeparatorLayerName";

@implementation UITableViewCell (MyAdditions)

-(CALayer *)separatorLayer
{
    for (CALayer *sublayer in self.layer.sublayers)
    {
        if ([sublayer.name isEqualToString:kUITablewViewCellSeparatorLayerName])
            return sublayer;
    }
    return nil;
}

-(CALayer *)newSeparatorLayer
{
    CALayer *separatorLayer = [CALayer layer];
    separatorLayer.name = kUITablewViewCellSeparatorLayerName;
    separatorLayer.frame = CGRectMake(0, self.bounds.size.height - 1, self.bounds.size.width, 1);
    separatorLayer.backgroundColor = [UIColor whiteColor].CGColor;
    [self.layer addSublayer:separatorLayer];
    return separatorLayer;
}

-(UITableViewCellSeparatorStyle)cellSeparatorStyle
{
    CALayer *separatorLayer = [self separatorLayer];
    if (separatorLayer == nil)
        return UITableViewCellSeparatorStyleNone;
    else
        return UITableViewCellSeparatorStyleSingleLine;
}

-(void)setCellSeparatorStyle:(UITableViewCellSeparatorStyle)separatorStyle
{
    CALayer *separatorLayer = [self separatorLayer];
    switch (separatorStyle)
    {
        case UITableViewCellSeparatorStyleNone:
            [separatorLayer removeFromSuperlayer];
            break;
        case UITableViewCellSeparatorStyleSingleLine:
            if (separatorLayer == nil)
                separatorLayer = [self newSeparatorLayer];
            break;
        default:
            @throw [NSException exceptionWithName:NSStringFromClass([self class]) reason:@"Unsupported separatorStyle" userInfo:nil];
            break;
    }
}

-(UIColor *)cellSeparatorColor
{
    CALayer *separatorLayer = [self separatorLayer];
    return [UIColor colorWithCGColor:separatorLayer.backgroundColor];
}

-(void)setCellSeparatorColor:(UIColor *)separatorColor
{
    CALayer *separatorLayer = [self separatorLayer];
    if (separatorLayer == nil)
        separatorLayer = [self newSeparatorLayer];
    separatorLayer.backgroundColor = separatorColor.CGColor;
}

@end

现在你可以做像这样的事情:
UITableViewCell *cell = ...
cell.cellSeparatorStyle = UITableViewCellSeparatorStyleSingleLine;
cell.cellSeparatorColor = [UIColor orangeColor];

值得注意的是,如果属性名不是cellSeparatorStyle而是separatorStyle,则无论如何单元格都会绘制自己奇怪的分隔符。因此,在您的UITableViewCell子类中不要创建这样的属性非常重要。 - Aleks N.

0

正如其他人所说,通常有两种方法来实现这个功能,一种是创建一个1像素的CALayerUIView分隔线并将其添加到contentView中。

随着时间的推移,我看到了多个项目以不同的方式实现此功能,有时甚至在同一个项目中也会有多种不同的实现方式。由于单元格重用,很容易引入错误,并且为了正确渲染像素线,必须合并屏幕比例:(1.0 / [UIScreen mainScreen].scale)

我创建了一个,它简化了这个过程,只需要一个单独的方法类,无需子类化。 https://github.com/kgaidis/KGViewSeparators

Objective-C:

[view kg_show:YES separator:KGViewSeparatorTop color:[UIColor blackColor] lineWidth:KGViewSeparatorLineWidth(1.0) insets:UIEdgeInsetsMake(0, 15.0, 0, 15.0)];

Swift:

view.kg_show(true, separator: .Bottom, color: UIColor.blackColor(), lineWidth: KGViewSeparatorLineWidth(1.0), insets: UIEdgeInsetsZero)

view.kg_show(true,separator:.Bottom,color:UIColor.blackColor(),lineWidth:KGViewSeparatorLineWidth(1.0),insets:UIEdgeInsetsZero)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接