How to customize tableView separator in iPhone
IphoneUitableviewIphone Problem Overview
By default there is a single line separator in uitableview.
But I want to put my customized line as a separator.
Is it possible? How?
Iphone Solutions
Solution 1 - Iphone
If you want to do more than change the color of the separator using the separatorColor property of the UITableView then you could set the separatorStyle property to UITableViewCellSeparatorStyleNone and then either:
- create custom UITableViewCells that include your custom seperator within them
- create alternate [UITableViewCell][6]s that include your custom separator
For example, if your table currently displays 5 rows you could update it to display 9 rows and the rows at index 1, 3, 5, 7 would be separator cells.
Solution 2 - Iphone
A better solution is to use the cell's current width and height. Something like this:
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height - 1.0, cell.contentView.frame.size.width, 1)];
lineView.backgroundColor = [UIColor darkGrayColor];
[cell.contentView addSubview:lineView];
Solution 3 - Iphone
If you need different seperator colors for different rows OR you want the seperator to remain visible when the row is highlighted on tap then try this:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// We have to use the borderColor/Width as opposed to just setting the
// backgroundColor else the view becomes transparent and disappears during
// the cell's selected/highlighted animation
UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 43, 1024, 1)];
separatorView.layer.borderColor = [UIColor redColor].CGColor;
separatorView.layer.borderWidth = 1.0;
[cell.contentView addSubview:separatorView];
This assumes your cell's background color is transparent.
The above solution came out of some extensive experimentation. Here's some notes on my findings that I'm sure will help people:
In the normal “not selected” state
- The contentView (whats in your XIB unless you coded it otherwise) is drawn normally
- The selectedBackgroundView is HIDDEN
- The backgroundView is visible (so provided your contentView is transparent you see the backgroundView or (if you have not defined a backgroundView you'll see the background colour of the UITableView itself)
A cell is selected, the following occurs immediately with-OUT any animation:
- All views/subviews within the contentView have their backgroundColor cleared (or set to transparent), label etc text color's change to their selected colour
- The selectedBackgroundView becomes visible (this view is always the full size of the cell (a custom frame is ignored, use a subview if you need to). Also note the backgroundColor of subViews are not displayed for some reason, perhaps they're set transparent like the contentView). If you didn't define a selectedBackgroundView then Cocoa will create/insert the blue (or gray) gradient background and display this for you)
- The backgroundView is unchanged
When the cell is deselected, an animation to remove the highlighting starts:
- The selectedBackgroundView alpha property is animated from 1.0 (fully opaque) to 0.0 (fully transparent).
- The backgroundView is again unchanged (so the animation looks like a crossfade between selectedBackgroundView and backgroundView)
- Only once the animation has finished does the contentView get redrawn in the "not-selected" state and its subview backgroundColor's become visible again (this can cause your animation to look horrible so it is advisable that you don't use UIView.backgroundColor in your contentView)
Solution 4 - Iphone
These answers result in the highlight rect being overwritten by the separator you add to your cell (on iOS 6 with my testing at least). You need to set the separatorColor
to [UIColor clearColor]
so that cells are still separated by 1px, you can then draw your separator in the gap:
- (void)viewDidLoad {
self.tableView.separatorColor = [UIColor clearColor];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// snip
CALayer *separator = [CALayer layer];
separator.backgroundColor = [UIColor redColor].CGColor;
separator.frame = CGRectMake(0, 43, self.view.frame.size.width, 1);
[cell.layer addSublayer:separator];
return cell;
}
Solution 5 - Iphone
You add the following code cellForRowAtIndexPath
delegate of tableView to create a custom image view of 1px height and 200px width for everyCell
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:lineView];
Note: i dont know how heavy it is on the performance.
Solution 6 - Iphone
I dont know if this can be done "automatically" with some setting. But a suggestion would be to set the line separator as none, and in the borders of your cells actually draw your line separator that you want..
Solution 7 - Iphone
If you are using Custom Cells in Swift: An alternative approach is to extend UITableViewCell with a function that can draw a line at the top of that cell.
import UIKit
extension UITableViewCell {
func addSeparatorLineToTop(){
let lineFrame = CGRectMake(0, 0, bounds.size.width, 1)
let line = UIView(frame: lineFrame)
line.backgroundColor = UIColor.myGray_300()
addSubview(line)
}
}
Then you can add this line to any custom cell, for example in the awakeFromNib
override func awakeFromNib() {
super.awakeFromNib()
addSeparatorLineToTop()
}
This solution is nice because it does not mess up your storyboard and limits your extra code to 1 line.
Solution 8 - Iphone
On a retina display, even drawing a 0.5 unit line will result in a two-pixel line, due to anti-aliasing. To render it as a single pixel on both displays, shift it up one quarter of a unit:
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, self.contentView.frame.size.height - (1.0 - 0.25), self.contentView.frame.size.wi
lineView.backgroundColor = [UIColor colorWithRed:(230.0/255.0f) green:(233/255.0f) blue:(237.0/255.0f) alpha:1.0f];
[self.contentView addSubview:lineView];
Solution 9 - Iphone
Tested on iOS 7 (GM):
@implementation MyTableViewController
- (void)viewDidLayoutSubviews {
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:NSClassFromString(@"_UITableViewCellSeparatorView")])
view.backgroundColor = [UIColor redColor];
}
}
@end
NOTE: it appears the UITableView moves separators to the cells in some configurations, which would make this code not work unless you descend into all UITableViewCells as well.
Solution 10 - Iphone
Swift version:
private let kSeparatorTag = 123
private let kSeparatorHeight: CGFloat = 1.5
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
{
if cell.viewWithTag(kSeparatorTag) == nil //add separator only once
{
let separatorView = UIView(frame: CGRectMake(0, cell.frame.height - kSeparatorHeight, cell.frame.width, kSeparatorHeight))
separatorView.tag = kSeparatorId
separatorView.backgroundColor = UIColor.redColor()
separatorView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
cell.addSubview(separatorView)
}
}
Solution 11 - Iphone
The cell in gist below is a UITableViewCell's subclass where each cell could have its own separator w/ many styles (currently only .None and .Default are supported). It is written in Swift and assumes Autolayout usage.
https://gist.github.com/evgeniyd/fa36b6f586a5850bca3f
How to use the class:
-
set UITableView object's separator style to
UITableViewCellSeparatorStyle.None
tableView.separatorStyle = .None
-
Create a subclass of
MPSTableViewCell
-
Somewhere inside
awakeFromNib()
set cell's separator style
Note: the code below assumes cell is loaded from xib/storyboard
class FASWorkoutCell: FASTableViewCell {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
separatorType = .Default
}
// ...
}
Solution 12 - Iphone
If you use a customized UITableViewCell, You can simply add UIView on the bottom of the UItableViewCell.xib and put the background colour as the colour you want.
For example, on xib I add a UIView on the bottom and set the height as 1. Using autolayout, I set left constraint to 12, bottom constraint to 0, right constraint to 0 and height to 1.