一般TableView設(shè)置全屏分隔線有下面三種方法
方法1:自定義cell, 手動添加分割線
首先先隱藏系統(tǒng)自帶的分割線, 接下來有2種做法 (建議使用做法a)
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
或者
self.tableView.separatorColor = [UIColor clearColor];
做法a: 可以通過addSubview的方式添加一條分割線
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
//自定義分割線方法一: 通過addSubview的方式添加一條分割線
//在自定義cell 里面給每個(gè)cell添加高度為2的紅色分割線
CGFloat cellH = cell.frame.size.height;
if(indexPath.row != cars.count - 1){
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, cellH-2, self.view.frame.size.width, 2)];
line.backgroundColor = [UIColor redColor];
[cell addSubview:line];
}
return cell;
}
- 做法b:也可以自定義cell, cell中重寫drawRect: 自繪分割線
// 自繪分割線
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillRect(context, rect);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
//繪制高度為2綠色分割線
CGContextStrokeRect(context, CGRectMake(0, rect.size.height - 2, rect.size.width, 2));
}
方法2:自定義cell , 重寫setFrame方法,cell高度-1,露出tableView背景色
- 首先隱藏系統(tǒng)分割線, 設(shè)置tableView背景顏色.
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// 設(shè)置tableView背景色
self.tableView.backgroundColor = [UIColor colorWithWhite:215 / 255.0 alpha:1];
- 在自定義cell中重寫setFrame:
- (void)setFrame:(CGRect)frame
{
frame.size.height -= 1;
// 給cellframe賦值
[super setFrame:frame];
}
方法3.利用系統(tǒng)屬性設(shè)置(separatorInset, layoutMargins), 共需添加四行代碼
- 對tableView的separatorInset, layoutMargins屬性的設(shè)置
-(void)viewDidLoad {
[super viewDidLoad];
//1.調(diào)整(iOS7以上)表格分隔線邊距
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
self.tableView.separatorInset = UIEdgeInsetsZero;
}
//2.調(diào)整(iOS8以上)view邊距(或者在cell中設(shè)置preservesSuperviewLayoutMargins,二者等效)
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
self.tableView.layoutMargins = UIEdgeInsetsZero;
}
}
- 對cell的LayoutMargins屬性的設(shè)置
- 補(bǔ)充:對cell的設(shè)置可以寫在cellForRowAtIndexPath里,也可以寫在willDisplayCell方法里
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
//2.調(diào)整(iOS8以上)tableView邊距(與上面第2步等效,二選一即可)
if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
cell.preservesSuperviewLayoutMargins = NO;
}
//3.調(diào)整(iOS8以上)view邊距
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
return cell;
}
三種方法優(yōu)缺點(diǎn)比較:
方法1 中做法a比較好用,可以使用系統(tǒng)自帶的cell, 但是需要添加一個(gè)view,設(shè)置背景顏色和frame. 而做法b僅僅為了分隔線卻還必須再自定義cell, 重寫drawRect,又顯得麻煩;
方法2比較取巧,但是也需要自定義cell,在某些情況下不允許改變tableView的背景色,使用場景有限;
方法3不需要自定義cell,對系統(tǒng)(iOS7,iOS8以上)做個(gè)簡單判斷即可.可惜網(wǎng)上很多文章寫的不對,很多人不會正確使用,有些會用的人也說不清楚原理,只管復(fù)制粘貼.
比如網(wǎng)上流傳的一般是這樣,需要四步,雖然真的管用,但多了一步[cell setSeparatorInset:UIEdgeInsetsZero];
而且原理也沒講,估計(jì)是某大神寫的,根本不屑于過多解釋,讓我用起來很郁悶,網(wǎng)上流傳代碼:
首先在viewDidLoad方法中加上如下代碼:
-(void)viewDidLoad {
[super viewDidLoad];
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
然后在willDisplayCell方法中加入如下代碼:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
分割線不能全屏原理解析
其實(shí)關(guān)于分隔線不能全屏的原理,蘋果官方在文件中已經(jīng)說明了,可以去看一下
在iOS7之前系統(tǒng)默認(rèn)就是全屏的,iOS7時(shí)
UITableView
多了separatorInset
屬性,可在UITableView
的頭文件中查看,如下:
@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
// allows customization of the frame of cell separators
iOS7時(shí)只要設(shè)置該屬性為
UIEdgeInsetsZero
就沒有問題了.iOS8之后僅僅完成以上設(shè)置就不行了,仔細(xì)查看后發(fā)現(xiàn)iOS8的
UIView
的頭文件里又多了個(gè)layoutMargins
屬性,并有官方注釋
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
/*
-layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the left edge of their superview's bounds
If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your view if the margins change.
*/
大意是說:layoutMargins是view的bounds的邊距,用來調(diào)整內(nèi)容默認(rèn)邊距
如果preservesSuperviewLayoutMargins屬性是YES,那么設(shè)置父控件的layoutMargins邊距,
就會影響所有子控件的相對于父控件bounds的layoutMargins邊距
如果你的view的子類在布局或者繪圖中使用了layoutMargins屬性,需要重寫-layoutMarginsDidChange 方法,
以便當(dāng)邊距改變時(shí)能刷新你的view
正是因?yàn)閘ayoutMargins是UIView的新增屬性,tablet和cell作為UIView的子類都有這個(gè)屬性,所以相比較iOS7系統(tǒng),iOS8之后就多了兩步,必須同時(shí)再對tableView和cell的layoutMargins屬性進(jìn)行處理,才能讓分隔線真正全屏.
同時(shí)官方注釋中對preservesSuperviewLayoutMargins(意即:維持父控件的布局邊距)屬性的說明,也正好能說明網(wǎng)上另一種方法不設(shè)置self.tableView.layoutMargins = UIEdgeInsetsZero;
而是設(shè)置cell.preservesSuperviewLayoutMargins = NO;
為什么也能起作用
弄清楚了這些原理,就可以更好的記憶和使用這些方法,不用每次都去舊代碼查找或者去百度了.
說到了最后,不知道大家有沒有覺得影響分隔線全屏的元兇layoutMargins屬性 稍微有點(diǎn)眼熟呢?其實(shí)它在另一個(gè)地方也做了不少惡,就在storyboard中:
PS:附效果圖如下:
設(shè)置之前效果圖:
設(shè)置完第1步self.tableView.separatorInset = UIEdgeInsetsZero;
后效果圖:
設(shè)置完第2步self.tableView.layoutMargins = UIEdgeInsetsZero;
后效果圖:
設(shè)置完第3步cell.layoutMargins = UIEdgeInsetsZero;
后效果圖:
由于筆者水平有限,文中如果有錯(cuò)誤的地方,或者有更好的方法咙崎,還望大神指出胳喷。
附上本文的所有 demo 下載鏈接,【GitHub】席吴。
如果你看完后覺得對你有所幫助正驻,還望在 GitHub 上點(diǎn)個(gè) star。贈人玫瑰抢腐,手有余香姑曙。