How do I add an extra separator to the top of a UITableView?
I have a view for the iPhone that is basically split in two, with an informational display in the top half, and a UITableView for selecting actions in the bottom half. The problem is that there is no border or separator above the first cell in the UITableView, so the first item in the list looks fun开发者_开发问答ny. How can I add an extra separator at the top of the table, to separate it from the display area above it?
Here's the code to build the cells - it's pretty straightforward. The overall layout is handled in a xib.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
switch(indexPath.row) {
case 0: {
cell.textLabel.text = @"Action 1";
break;
}
case 1: {
cell.textLabel.text = @"Action 2";
break;
}
// etc.......
}
return cell;
}
To replicate the standard iOS separator lines, I use a 1 px (not 1 pt) hair line tableHeaderView
with the table view's separatorColor
:
// in -viewDidLoad
self.tableView.tableHeaderView = ({
UIView *line = [[UIView alloc]
initWithFrame:CGRectMake(0, 0,
self.tableView.frame.size.width, 1 / UIScreen.mainScreen.scale)];
line.backgroundColor = self.tableView.separatorColor;
line;
});
The same in Swift (thanks, Dane Jordan, Yuichi Kato, Tony Merritt):
let px = 1 / UIScreen.main.scale
let frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.width, height: px)
let line = UIView(frame: frame)
self.tableView.tableHeaderView = line
line.backgroundColor = self.tableView.separatorColor
I just got hit with this same problem and realised that the separator at the top is only displayed whilst scrolling the table.
What I then did was the following
- In Interface Builder go to "Scroll View Size"
- Set the Content Insets of Top to 1
Alternatively in code you could do
[tableView setContentInset:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)];
NOTE: This no longer works for iOS7 as the separators are no longer shown at all.
I had the same problem and could not find an answer. So I added a line to the bottom of my table header.
CGRect tableFrame = [[self view] bounds] ;
CGFloat headerHeight = 100;
UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,tableFrame.size.width, headerHeight)];
// Add stuff to my table header...
// Create separator
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, headerHeight-1, tableFrame.size.width, 1)] ;
lineView.backgroundColor = [UIColor colorWithRed:224/255.0 green:224/255.0 blue:224/255.0 alpha:1.0];
[headerView addSubview:lineView];
self.tableView.tableHeaderView = headerView;
Swift 4
extension UITableView {
func addTableHeaderViewLine() {
self.tableHeaderView = {
let line = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: 1 / UIScreen.main.scale))
line.backgroundColor = self.separatorColor
return line
}()
}
}
I made a UITableView extension that displays a native style separator on top of the UITableView, while the table gets scrolled.
Here's the code
fileprivate var _topSeparatorTag = 5432 // choose unused tag
extension UITableView {
fileprivate var _topSeparator: UIView? {
return superview?.subviews.filter { $0.tag == _topSeparatorTag }.first
}
override open var contentOffset: CGPoint {
didSet {
guard let topSeparator = _topSeparator else { return }
let shouldDisplaySeparator = contentOffset.y > 0
if shouldDisplaySeparator && topSeparator.alpha == 0 {
UIView.animate(withDuration: 0.15, animations: {
topSeparator.alpha = 1
})
} else if !shouldDisplaySeparator && topSeparator.alpha == 1 {
UIView.animate(withDuration: 0.25, animations: {
topSeparator.alpha = 0
})
}
}
}
// Adds a separator to the superview at the top of the table
// This needs the separator insets to be set on the tableView, not the cell itself
func showTopSeparatorWhenScrolled(_ enabled: Bool) {
if enabled {
if _topSeparator == nil {
let topSeparator = UIView()
topSeparator.backgroundColor = separatorColor?.withAlphaComponent(0.85) // because while scrolling, the other separators seem lighter
topSeparator.translatesAutoresizingMaskIntoConstraints = false
superview?.addSubview(topSeparator)
topSeparator.leftAnchor.constraint(equalTo: self.leftAnchor, constant: separatorInset.left).isActive = true
topSeparator.rightAnchor.constraint(equalTo: self.rightAnchor, constant: separatorInset.right).isActive = true
topSeparator.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
let onePixelInPoints = CGFloat(1) / UIScreen.main.scale
topSeparator.heightAnchor.constraint(equalToConstant: onePixelInPoints).isActive = true
topSeparator.tag = _topSeparatorTag
topSeparator.alpha = 0
superview?.setNeedsLayout()
}
} else {
_topSeparator?.removeFromSuperview()
}
}
func removeSeparatorsOfEmptyCells() {
tableFooterView = UIView(frame: .zero)
}
}
To enable it, simply call tableView.showTopSeparatorWhenScrolled(true)
after you set your delegate
for your UITableView
In complement of Ortwin's answer, if you need to add some margin to your top separator to fit the separator inset, you have to embedded your top separator in another view :
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1 / UIScreen.mainScreen.scale)];
UIView *topSeparator = [[UIView alloc] initWithFrame:CGRectMake(self.tableView.separatorInset.left, 0, self.tableView.frame.size.width - self.tableView.separatorInset.left - self.tableView.separatorInset.right, 1 / UIScreen.mainScreen.scale)];
topSeparator.backgroundColor = self.tableView.separatorColor;
[headerView addSubview:topSeparator];
self.tableView.tableHeaderView = headerView;
Hope it helps.
I solved this by adding one extra line at the beginning of the table. Just have to set its height to 1, set its the text to empty, disable user interaction for it and in the whole code adjust the indexPath.row value.
Add a separator between header view and first row :- In view for Header in section delegate method add a subview self.separator //@property (nonatomic, strong) UIImageView *separator;
- (CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section {
return 41;
}
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section {
self.headerView = [[UIView alloc] init];
self.headerView.backgroundColor = [UIUtils colorForRGBColor:TIMESHEET_HEADERVIEW_COLOR];
self.separator = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"seperator.png"]];
self.separator.frame = CGRectMake(0,40,self.view.frame.size.width,1);
[self.headerView addSubview:self.separator];
return self.headerView;
}
精彩评论