In my app, I use a UITableView
My problem is that I want to remove the last border of the last cell in UITableView
.
Please check the following image:
In my app, I use a UITableView
My problem is that I want to remove the last border of the last cell in UITableView
.
Please check the following image:
The best solution is add a footer view. The following code hide the last cell's line perfectly:
Objective-C
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1)];
Swift 4.0
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 1))
In iOS 7 there is an easier solution. Supposing cell is your last cell:
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0);
Updated on 9/14/15. My original answer become obsolete, but it is still a universal solution for all iOS versions:
You can hide tableView
's standard separator line, and add your custom line at the top of each cell. The easiest way to add custom separator is to add simple UIView
of 1px height:
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width, 1)];
separatorLineView.backgroundColor = [UIColor grayColor];
[cell.contentView addSubview:separatorLineView];
To date, I subscribe to another way for hiding extra separators below cells (works for iOS 6.1+):
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
This works for me in iOS 7 and 8:
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, CGRectGetWidth(tableView.bounds));
NOTE: be careful about using tableView.bounds
as it sometimes reports the wrong value depending on when you call it. See Reporting incorrect bounds in landscape Mode
Add this line of code in viewDidLoad()
.
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.001))
This make sure the last separator will be replaced and replaced (invisible) footer view will not occupy any extra height. Since the footer view's width will be managed by UITableView
, so you can set it to 0.
Extension based solution for Swift 4, tested on iOS 12
I noticed that setting a empty view of height = 1
also removes the separator of the last visible cell however setting height = 0
just removes the separator of the empty cells
extension UITableView {
func removeSeparatorsOfEmptyCells() {
tableFooterView = UIView(frame: .zero)
}
func removeSeparatorsOfEmptyCellsAndLastCell() {
tableFooterView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 0, height: 1)))
}
}
In Swift simply:
tableView.tableFooterView = UIView()
Here is the remedy I currently use. it might not be the best approach, but it works.
Remove SeparatorColor and setSeparatorStyle to make custom separator
- (void)viewDidLoad
{
[super viewDidLoad];
...
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.tableView setSeparatorColor:[UIColor clearColor]];
}
Add custom separator to each cell with tableview background
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
...
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.frame.size.height-1, 320, 1)];
separatorLineView.backgroundColor = self.tableView.backgroundColor;
[cell.contentView addSubview:separatorLineView];
return cell;
}
_tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
For iOS 7 and above
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL bIsLastRow = NO;
//Add logic to check last row for your data source
NSDictionary *dict = [_arrDataSource objectAtIndex:indexPath.section];
if([_arrDataSource lastObject] == dict)
{
bIsLastRow = YES;
}
//Set last row separate inset left value large, so it will go outside of view
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
{
[cell setSeparatorInset:UIEdgeInsetsMake(0, bIsLastRow ? 1000 :0, 0, 0)];
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) {
cell.separatorInset.right = cell.bounds.size.width
}
}
Swift 4.2
To get a separator that goes from left to right in your last cell, add this in your UITableViewDataSource's
tableView(_:cellForRowAt:)
implementation:
if tableView.numberOfRows(inSection: indexPath.section) - 1 == indexPath.row {
cell.separatorInset = .zero
}
If you don't want a separator for one particular cell, consider drawing your own separator and set tableView.separatorStyle = .none
.
Xcode 12, Swift 5
for removing separator after last cell, select grouped UITableView style You can do that in Interface Builder or setup it in viewDidLoad
tableView.style = UITableView.Style.grouped
remove empty space before first cell, write this code in viewDidLoad:
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 0.1))
for removing empty space before your cells, and you are going to scroll it under the navigation bar or have other difficulties with avoiding empty space, try to constraint your table to controller's super view Here double click the top constraint and then choose 'SuperView.Top' at the constraint settings
If you want full width separator or your own width of it, just select Separator Inset as Custom, and configure to your values, or write it in viewDidLoad:
tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
This works great for me:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell = cell as? yourCell else {
return
}
// Here we're checking if your cell is the last one
if indexPath.row == numberOfCells.count - 1 {
cell.separatorInset.left = UIScreen.main.bounds.width
}
}
What we're doing here is setting the size of the left inset to be a big enough value so that the separator line won't be visible anymore. So when we increase the size value of our inset it will get closer and closer to the right of our screen since left inset goes towards the right direction.
Find the last cell index in the cellForRow
delegate and put the line of code from below:
cell.separatorInset = UIEdgeInsetsMake(
0.f,
40.0f,
0.f,
self.view.frame.size.width-40.0f
);
Another option is by subclassing UITableView
:
@synthesize hideLastSeparator = _hideLastSeparator;
@synthesize hideLastSeparatorView = _hideLastSeparatorView;
-(void)setHideLastSeparator:(BOOL)hideLastSeparator {
if (_hideLastSeparator == hideLastSeparator) {
return;
}
_hideLastSeparator = hideLastSeparator;
if (_hideLastSeparator) {
_hideLastSeparatorView = [[UIView alloc] initWithFrame:CGRectMake(0, self.contentSize.height, self.bounds.size.width, 0.5f)];
_hideLastSeparatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
_hideLastSeparatorView.backgroundColor = self.backgroundColor;
[self addSubview:_hideLastSeparatorView];
[self hideSeparator];
}
else {
[_hideLastSeparatorView removeFromSuperview];
_hideLastSeparatorView = nil;
}
}
-(void)setContentSize:(CGSize)contentSize {
[super setContentSize:contentSize];
if (_hideLastSeparator) {
[self hideSeparator];
}
}
-(void)hideSeparator {
CGRect frame = _hideLastSeparatorView.frame;
frame.origin.y = self.contentSize.height - frame.size.height;
_hideLastSeparatorView.frame = frame;
}
The .h should only contain property declarations for hideLastSeparator
and hideLastSeparatorView
.
When wanting to hide the separator, use the new class and set myTableView.hideLastSeparator = YES
.
The way this works is by obstructing the last separator by adding a new view over it.
This is somewhat easier to use in my opinion (than using a custom separator, or setting the last separatorInset of the last cell), and avoids some weird animations that the method of setting a tableFooterView
sometimes causes (e.g. during row insertion/deletion or other table animations).
If you're using custom separators for your UITableViewCell
the best solution is:
separatorView
class YourCell: UITableViewCell {
// Your implementation goes here...
// Separator view in cell
@IBOutlet private weak var separatorView: UIView!
// This function hides the separator view
func hideSeparator() {
separatorView.isHidden = true
}
}
tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
calculate if the cell is the last and hides it's separatorpublic func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell = cell as? YourCell else {
return
}
// Here we're checking if your cell is the last one
if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
// if true -> then hide it
cell.hideSeparator()
}
}
I tested and is working in Swift 5, iOS 15 and in xCode 13.3.1, Just Paste this code in TableView "cellForRowAt" method just before return cell as it pushes last line out of the frame....Note:-("arrayCartItems" will be your Array which you are returning in "numberOfRowsInSection" and "tblVw" is your Outlet name of UITableView in ViewController) Written in detail so that even Newbies could easily learn:)
if indexPath.row == arrayCartItems.count - 1 {
cell.separatorInset = UIEdgeInsets.init(top: 0, left: tblVw.bounds.width + 1, bottom: 0, right: 0)
} else {
cell.separatorInset = .zero
}
The most suitable & easy way would be using this at cellForRowAt
cell.drawBottonLine = (indexPath.row != sections[0].rows.count - 1)
Expanding on Tonny Xu's answer, I have multiple sections and this seems to work for removing the last cells separator
if(indexPath.row == [self.tableView numberOfRowsInSection:indexPath.section] - 1)
{
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1)];
}
In the cellForRowAtIndexPath
datasource