I'm customizing a UITableView
. I want to hide the line separating on the last cell ... can i do this?
I know I can do tableView.separatorStyle = UITableViewCellStyle.None
but that would affect all the cells of the tableView. I want it to only affect my last cell.
in viewDidLoad
, add this line:
self.tableView.separatorColor = [UIColor clearColor];
and in cellForRowAtIndexPath
:
for iOS lower versions
if(indexPath.row != self.newCarArray.count-1){
UIImageView *line = [[UIImageView alloc] initWithFrame:CGRectMake(0, 44, 320, 2)];
line.backgroundColor = [UIColor redColor];
[cell addSubview:line];
}
for iOS 7 upper versions (including iOS 8)
if (indexPath.row == self.newCarArray.count-1) {
cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.f);
}
You can use the following code:
Swift :
if indexPath.row == {your row number} {
cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: .greatestFiniteMagnitude)
}
or :
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, UIScreen.main.bounds.width)
for default Margin:
cell.separatorInset = UIEdgeInsetsMake(0, tCell.layoutMargins.left, 0, 0)
to show separator end-to-end
cell.separatorInset = .zero
Objective-C:
if (indexPath.row == {your row number}) {
cell.separatorInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, CGFLOAT_MAX);
}
To follow up on Hiren's answer.
in ViewDidLoad and the following line :
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
Or, if you are using XIB's or Storyboards change "separator" to "none" :
And in CellForRowAtIndexPath add this :
CGFloat separatorInset; // Separator x position
CGFloat separatorHeight;
CGFloat separatorWidth;
CGFloat separatorY;
UIImageView *separator;
UIColor *separatorBGColor;
separatorY = cell.frame.size.height;
separatorHeight = (1.0 / [UIScreen mainScreen].scale); // This assures you to have a 1px line height whatever the screen resolution
separatorWidth = cell.frame.size.width;
separatorInset = 15.0f;
separatorBGColor = [UIColor colorWithRed: 204.0/255.0 green: 204.0/255.0 blue: 204.0/255.0 alpha:1.0];
separator = [[UIImageView alloc] initWithFrame:CGRectMake(separatorInset, separatorY, separatorWidth,separatorHeight)];
separator.backgroundColor = separatorBGColor;
[cell addSubView: separator];
Here is an example of the result where I display a tableview with dynamic Cells (but only have a single one with contents). The result being that only that one has a separator and not all the "dummy" ones tableview automatically adds to fill the screen.
Hope this helps.
EDIT: For those who don't always read the comments, there actually is a better way to do it with a few lines of code :
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
}
If you don't want to draw the separator yourself, use this:
// Hide the cell separator by moving it to the far right
cell.separatorInset = UIEdgeInsetsMake(0, 10000, 0, 0);
This API is only available starting from iOS 7 though.
my develop environment is
- Xcode 7.0
- 7A220 Swift 2.0
- iOS 9.0
above answers not fully work for me
after try, my finally working solution is:
let indent_large_enought_to_hidden:CGFloat = 10000
cell.separatorInset = UIEdgeInsetsMake(0, indent_large_enought_to_hidden, 0, 0) // indent large engough for separator(including cell' content) to hidden separator
cell.indentationWidth = indent_large_enought_to_hidden * -1 // adjust the cell's content to show normally
cell.indentationLevel = 1 // must add this, otherwise default is 0, now actual indentation = indentationWidth * indentationLevel = 10000 * 1 = -10000
In Swift 3 and Swift 4, you can write an extension to UITableViewCell like this:
extension UITableViewCell {
func hideSeparator() {
self.separatorInset = UIEdgeInsets(top: 0, left: self.bounds.size.width, bottom: 0, right: 0)
}
func showSeparator() {
self.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
Then you can use this as below (when cell is your cell instance):
cell.hideSeparator()
cell.showSeparator()
It is really better assigning the width of table view cell as left inset instead of assigning it some random number. Because in some screen dimensions, maybe not now but in future your separators can still be visible because that random number may not be enough. Also, in iPad in landscape mode you can't guarantee that your separators will always be invisible.
Better solution for iOS 7 & 8
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
DLog(@"");
if (cell && indexPath.row == 0 && indexPath.section == 0) {
DLog(@"cell.bounds.size.width %f", cell.bounds.size.width);
cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.0f);
}
}
If your app is rotatable — use 3000.0f for left inset constant or calc it on the fly. If you try to set right inset you have visible part of separator on the left side of cell on iOS 8.
In iOS 7, the UITableView grouped style cell separator looks a bit different. It looks a bit like this:
I tried Kemenaran's answer of doing this:
cell.separatorInset = UIEdgeInsetsMake(0, 10000, 0, 0);
However that doesn't seem to work for me. I'm not sure why. So I decided to use Hiren's answer, but using UIView
instead of UIImageView
, and draws the line in the iOS 7 style:
UIColor iOS7LineColor = [UIColor colorWithRed:0.82f green:0.82f blue:0.82f alpha:1.0f];
//First cell in a section
if (indexPath.row == 0) {
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1)];
line.backgroundColor = iOS7LineColor;
[cell addSubview:line];
[cell bringSubviewToFront:line];
} else if (indexPath.row == [self.tableViewCellSubtitles count] - 1) {
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(21, 0, self.view.frame.size.width, 1)];
line.backgroundColor = iOS7LineColor;
[cell addSubview:line];
[cell bringSubviewToFront:line];
UIView *lineBottom = [[UIView alloc] initWithFrame:CGRectMake(0, 43, self.view.frame.size.width, 1)];
lineBottom.backgroundColor = iOS7LineColor;
[cell addSubview:lineBottom];
[cell bringSubviewToFront:lineBottom];
} else {
//Last cell in the table view
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(21, 0, self.view.frame.size.width, 1)];
line.backgroundColor = iOS7LineColor;
[cell addSubview:line];
[cell bringSubviewToFront:line];
}
If you use this, make sure you plug in the correct table view height in the second if statement. I hope this is useful for someone.
In your UITableViewCell subclass, override layoutSubviews and hide the _UITableViewCellSeparatorView. Works under iOS 10.
override func layoutSubviews() {
super.layoutSubviews()
subviews.forEach { (view) in
if view.dynamicType.description() == "_UITableViewCellSeparatorView" {
view.hidden = true
}
}
}
Set separatorInset.right = .greatestFiniteMagnitude
on your cell.
In Swift using iOS 8.4:
/*
Tells the delegate that the table view is about to draw a cell for a particular row. (optional)
*/
override func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath)
{
if indexPath.row == 3 {
// Hiding separator line for only one specific UITableViewCell
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0)
}
}
Note: this snippet above will work on UITableView using dynamic cells. The only problem that you can encounter is when you use static cells with categories, a separator type different than none and a grouped style for the table view. In fact, in this particular case it will not hide the last cell of each category. For overcoming that, the solution that I found was to set the cell separator (through IB) to none and then creating and adding manually (through code) your line view to each cell. For an example, please check the snippet below:
/*
Tells the delegate that the table view is about to draw a cell for a particular row. (optional)
*/
override func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath)
{
// Row 2 at Section 2
if indexPath.row == 1 && indexPath.section == 1 {
// Hiding separator line for one specific UITableViewCell
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0)
// Here we add a line at the bottom of the cell (e.g. here at the second row of the second section).
let additionalSeparatorThickness = CGFloat(1)
let additionalSeparator = UIView(frame: CGRectMake(0,
cell.frame.size.height - additionalSeparatorThickness,
cell.frame.size.width,
additionalSeparatorThickness))
additionalSeparator.backgroundColor = UIColor.redColor()
cell.addSubview(additionalSeparator)
}
}
Use this subclass, set separatorInset
does not work for iOS 9.2.1, content would be squeezed.
@interface NSPZeroMarginCell : UITableViewCell
@property (nonatomic, assign) BOOL separatorHidden;
@end
@implementation NSPZeroMarginCell
- (void) layoutSubviews {
[super layoutSubviews];
for (UIView *view in self.subviews) {
if (![view isKindOfClass:[UIControl class]]) {
if (CGRectGetHeight(view.frame) < 3) {
view.hidden = self.separatorHidden;
}
}
}
}
@end
I do not believe this approach will work under any circumstance with dynamic cells...
if (indexPath.row == self.newCarArray.count-1) {
cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.f);
}
It doesn't matter which tableview method you do it in for dynamic cells the cell you changed the inset property on will always have the inset property set now every time it is dequeued causing a rampage of missing line separators... That is until you change it yourself.
Something like this worked for me:
if indexPath.row == franchises.count - 1 {
cell.separatorInset = UIEdgeInsetsMake(0, cell.contentView.bounds.width, 0, 0)
} else {
cell.separatorInset = UIEdgeInsetsMake(0, 0, cell.contentView.bounds.width, 0)
}
That way you update ur data structure state at every load
Using Swift 3 and adopting the fastest hacking-method, you can improve code using extensions:
extension UITableViewCell {
var isSeparatorHidden: Bool {
get {
return self.separatorInset.right != 0
}
set {
if newValue {
self.separatorInset = UIEdgeInsetsMake(0, self.bounds.size.width, 0, 0)
} else {
self.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}
}
}
}
Then, when you configure cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath)
switch indexPath.row {
case 3:
cell.isSeparatorHidden = true
default:
cell.isSeparatorHidden = false
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if cell.isSeparatorHidden {
// do stuff
}
}
The much more simple and logical is to do this:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return [[UIView alloc] initWithFrame:CGRectZero];
}
In most cases you don't want to see only the last tableCiewCell separator. And this approach removes only the last tableViewCell separator, and you don't need to think about autolayout issues (i.e. rotating device) or hardcode values to set up separator insets.
In willdisplaycell
:
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0)
if([_data count] == 0 ){
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];// [self tableView].=YES;
} else {
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];//// [self tableView].hidden=NO;
}
The best way to achieve this is to turn off default line separators, subclass UITableViewCell
and add a custom line separator as a subview of the contentView
- see below a custom cell that is used to present an object of type SNStock
that has two string properties, ticker
and name
:
import UIKit
private let kSNStockCellCellHeight: CGFloat = 65.0
private let kSNStockCellCellLineSeparatorHorizontalPaddingRatio: CGFloat = 0.03
private let kSNStockCellCellLineSeparatorBackgroundColorAlpha: CGFloat = 0.3
private let kSNStockCellCellLineSeparatorHeight: CGFloat = 1
class SNStockCell: UITableViewCell {
private let primaryTextColor: UIColor
private let secondaryTextColor: UIColor
private let customLineSeparatorView: UIView
var showsCustomLineSeparator: Bool {
get {
return !customLineSeparatorView.hidden
}
set(showsCustomLineSeparator) {
customLineSeparatorView.hidden = !showsCustomLineSeparator
}
}
var customLineSeparatorColor: UIColor? {
get {
return customLineSeparatorView.backgroundColor
}
set(customLineSeparatorColor) {
customLineSeparatorView.backgroundColor = customLineSeparatorColor?.colorWithAlphaComponent(kSNStockCellCellLineSeparatorBackgroundColorAlpha)
}
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(reuseIdentifier: String, primaryTextColor: UIColor, secondaryTextColor: UIColor) {
self.primaryTextColor = primaryTextColor
self.secondaryTextColor = secondaryTextColor
self.customLineSeparatorView = UIView(frame:CGRectZero)
super.init(style: UITableViewCellStyle.Subtitle, reuseIdentifier:reuseIdentifier)
selectionStyle = UITableViewCellSelectionStyle.None
backgroundColor = UIColor.clearColor()
contentView.addSubview(customLineSeparatorView)
customLineSeparatorView.hidden = true
}
override func prepareForReuse() {
super.prepareForReuse()
self.showsCustomLineSeparator = false
}
// MARK: Layout
override func layoutSubviews() {
super.layoutSubviews()
layoutCustomLineSeparator()
}
private func layoutCustomLineSeparator() {
let horizontalPadding: CGFloat = bounds.width * kSNStockCellCellLineSeparatorHorizontalPaddingRatio
let lineSeparatorWidth: CGFloat = bounds.width - horizontalPadding * 2;
customLineSeparatorView.frame = CGRectMake(horizontalPadding,
kSNStockCellCellHeight - kSNStockCellCellLineSeparatorHeight,
lineSeparatorWidth,
kSNStockCellCellLineSeparatorHeight)
}
// MARK: Public Class API
class func cellHeight() -> CGFloat {
return kSNStockCellCellHeight
}
// MARK: Public API
func configureWithStock(stock: SNStock) {
textLabel!.text = stock.ticker as String
textLabel!.textColor = primaryTextColor
detailTextLabel!.text = stock.name as String
detailTextLabel!.textColor = secondaryTextColor
setNeedsLayout()
}
}
To disable the default line separator use, tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
. The consumer side is relatively simple, see example below:
private func stockCell(tableView: UITableView, indexPath:NSIndexPath) -> UITableViewCell {
var cell : SNStockCell? = tableView.dequeueReusableCellWithIdentifier(stockCellReuseIdentifier) as? SNStockCell
if (cell == nil) {
cell = SNStockCell(reuseIdentifier:stockCellReuseIdentifier, primaryTextColor:primaryTextColor, secondaryTextColor:secondaryTextColor)
}
cell!.configureWithStock(stockAtIndexPath(indexPath))
cell!.showsCustomLineSeparator = true
cell!.customLineSeparatorColor = tintColor
return cell!
}
if the accepted answer doesn't work, you can try this:
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.01f; }
It's great ;)
Swift:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
// remove separator for last cell
cell.separatorInset = indexPath.row < numberOfRowsInSection-1
? tableView.separatorInset
: UIEdgeInsets(top: 0, left: tableView.bounds.size.width, bottom: 0, right: 0)
return cell
}
Objective-C:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
// remove separator for last cell
cell.separatorInset = (indexPath.row < numberOfRowsInSection-1)
? tableView.separatorInset
: UIEdgeInsetsMake(0.f, tableView.bounds.size.width, 0.f, 0.f);
return cell;
}
Try the below code, might help you resolve your problem
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* reuseIdentifier = @"Contact Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (nil == cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
if (indexPath.row != 10) {//Specify the cell number
cell.backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bgWithLine.png"]];
} else {
cell.backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bgWithOutLine.png"]];
}
}
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellId = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
NSInteger lastRowIndexInSection = [tableView numberOfRowsInSection:indexPath.section] - 1;
if (row == lastRowIndexInSection) {
CGFloat halfWidthOfCell = cell.frame.size.width / 2;
cell.separatorInset = UIEdgeInsetsMake(0, halfWidthOfCell, 0, halfWidthOfCell);
}
}
You have to take custom cell and add Label and set constraint such as label should cover entire cell area. and write the below line in constructor.
- (void)awakeFromNib {
// Initialization code
self.separatorInset = UIEdgeInsetsMake(0, 10000, 0, 0);
//self.layoutMargins = UIEdgeInsetsZero;
[self setBackgroundColor:[UIColor clearColor]];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
}
Also set UITableView Layout margin as follow
tblSignup.layoutMargins = UIEdgeInsetsZero;
I couldn't hide the separator on a specific cell except using the following workaround
- (void)layoutSubviews {
[super layoutSubviews];
[self hideCellSeparator];
}
// workaround
- (void)hideCellSeparator {
for (UIView *view in self.subviews) {
if (![view isKindOfClass:[UIControl class]]) {
[view removeFromSuperview];
}
}
}
For Swift 2:
add the following line to viewDidLoad()
:
tableView.separatorColor = UIColor.clearColor()
For iOS7 and above, the cleaner way is to use INFINITY instead of hardcoded value. You don't have to worry on updating the cell when the screen rotates.
if (indexPath.row == <row number>) {
cell.separatorInset = UIEdgeInsetsMake(0, INFINITY, 0, 0);
}
As (many) others have pointed out, you can easily hide all UITableViewCell separators by simply turning them off for the entire UITableView itself; eg in your UITableViewController
- (void)viewDidLoad {
...
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
...
}
Unfortunately, its a real PITA to do on a per-cell basis, which is what you are really asking.
Personally, I've tried numerous permutations of changing the cell.separatorInset.left
, again, as (many) others have suggested, but the problem is, to quote Apple (emphasis added):
"...You can use this property to add space between the current cell’s contents and the left and right edges of the table. Positive inset values move the cell content and cell separator inward and away from the table edges..."
So if you try to 'hide' the separator by shoving it offscreen to the right, you can end up also indenting your cell's contentView too. As suggested by crifan, you can then try to compensate for this nasty side-effect by setting cell.indentationWidth
and cell.indentationLevel
appropriately to move everything back, but I've found this to also be unreliable (content still getting indented...).
The most reliable way I've found is to over-ride layoutSubviews
in a simple UITableViewCell subclass and set the right inset so that it hits the left inset, making the separator have 0 width and so invisible [this needs to be done in layoutSubviews to automatically handle rotations]. I also add a convenience method to my subclass to turn this on.
@interface MyTableViewCellSubclass()
@property BOOL separatorIsHidden;
@end
@implementation MyTableViewCellSubclass
- (void)hideSeparator
{
_separatorIsHidden = YES;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (_separatorIsHidden) {
UIEdgeInsets inset = self.separatorInset;
inset.right = self.bounds.size.width - inset.left;
self.separatorInset = inset;
}
}
@end
Caveat: there isn't a reliable way to restore the original right inset, so you cant 'un-hide' the separator, hence why I'm using an irreversible hideSeparator
method (vs exposing separatorIsHidden). Please note the separatorInset persists across reused cells so, because you can't 'un-hide', you need to keep these hidden-separator cells isolated in their own reuseIdentifier.
My requirement was to hide the separator between 4th and 5th cell. I achieved it by
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 3)
{
cell.separatorInset = UIEdgeInsetsMake(0, cell.bounds.size.width, 0, 0);
}
}
来源:https://stackoverflow.com/questions/8561774/hide-separator-line-on-one-uitableviewcell