UITableView separator line disappears when selecting cells in iOS7

In my View table, I set a dividing line between cells. I allow the selection of multiple cells. Here is my code for setting the selected cell background color:

UIView *cellBackgroundColorView = [[UIView alloc] initWithFrame:cell.frame]; [cellBackgroundColorView setBackgroundColor:[UIColor darkGray]]; [cell setSelectedBackgroundView:cellBackgroundColorView]; 

The problem is that if two adjacent cells are selected, between them there is no iOS7 dividing line, while in iOS6 there is (as expected).

I even tried setting the height of the cellBackgroundColorView frame to the height of cell.frame - 1.0 , but that doesn't work either.

Any ideas?

+46
uitableview ios7
Oct 06 '13 at 18:38
source share
22 answers

I haven’t received it yet until the end (at first glance it seems like an iOS 7 error ..), but I found a workaround. In tableView: didSelectRowAtIndexPath, if you send both messages below, the problem is visually resolved (with a probable cost of execution).

 [tableView deselectRowAtIndexPath:indexPath animated:YES]; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 

For this (for me) deselectRowAtIndexPath: animated: should contain animated: YES. The animation used for reloadRowsAtIndexPaths: withRowAnimation: does not matter.

+37
07 Oct '13 at
source share

Add this code to the cell for the row by indexpath

 cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.backgroundColor = [UIColor clearColor]; 
+21
Dec 17 '13 at 10:24
source share

in my case, I was an animation of a string, so I just needed to add the following:

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView beginUpdates]; [tableView deselectRowAtIndexPath:indexPath animated:NO]; //if you are doing any animation you have deselect the row here inside. [tableView endUpdates]; } 
+15
Dec 10 '14 at 19:48
source share

@samvermette answer solved the problem for me, but first I had to deselect the selected Row.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //Deselect Row [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; // fix for separators bug in iOS 7 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; } 
+12
Apr 21 '14 at 11:46
source share

This still seems to be a problem with iOS 7.0.3, but I worked with it using inexhaustible fake separator tools.

First set the UITableView separator style to UITableViewCellSeparatorStyleNone . Then you can use a custom subclass of UITableViewCell to fake a separator between cells for selected and unselected states:

 @implementation MyTableViewCellSubclass - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { CGRect frame = self.bounds; frame.origin.y = frame.size.height - 1.f; frame.size.height = 1.f; // Selected background view // UIView * separatorView = [[UIView alloc] initWithFrame:frame]; separatorView.backgroundColor = [UIColor darkGrayColor]; separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin; UIView * selectedView = [[UIView alloc] initWithFrame:self.bounds]; selectedView.backgroundColor = [UIColor lightGrayColor]; [selectedView addSubview:separatorView]; self.selectedBackgroundView = selectedView; // Add separator view to content view for unselected state // UIView * separatorView2 = [[UIView alloc] initWithFrame:frame]; separatorView2.backgroundColor = [UIColor darkGrayColor]; separatorView2.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin; [self.contentView addSubview:separatorView2]; } return self; } @end 
+4
Oct 28 '13 at 9:06 on
source share

This simple call made it for me on iOS 8.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // .... [tableView deselectRowAtIndexPath:indexPath animated:YES] // .... } 
+4
Nov 06 '14 at 23:07
source share

This will happen if you allow iOS to use its own default cell style. The best work I've found so far is to override the selected property implementation:

in the implementation of your cell subclass:

  @synthesize selected = _selected; 

in the initialization method:

  // problem actually is caused when you set following // to UITableViewCellSelectionStyleDefault, so: [self setSelectionStyle:UITableViewCellSelectionStyleNone]; 

override methods:

  - (BOOL)selected { return _selected; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { _selected = selected if (selected) { // apply your own selected style } else { // apply your own deselected style } } 
+3
Aug 15 '14 at 5:48
source share

I solved this problem (hacky) by reloading not only the selected cell, but also reloading it directly above it. None of the other solutions above worked for me.

  NSIndexPath *indexPathOfCellAbove = [NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section]; if (indexPath.row > 0) [self.tableView reloadRowsAtIndexPaths:@[indexPathOfCellAbove, indexPath] withRowAnimation:UITableViewRowAnimationNone]; else [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 
+2
Jan 09 '14 at 22:22
source share

- cellForRowAtIndexPath

 Create two separator views (sv1, sv2) [cell addsubview:sv1]; [cell.selectedBackgroundView addsubview:sv2]; 

- didSelectRowAtIndexPath

 [tableView deselectRowAtIndexPath:indexPath animated:NO]; 
+2
May 07 '14 at 12:34 a.m.
source share

For me, this happened when I programmatically installed:

 cell.selectionStyle = UITableViewCellSelectionStyleNone; 

When I set this property in the storyboard, it works fine.

+1
Apr 27 '15 at 13:04 on
source share

I ran into this problem when I did not set the cell selection style in any programmatic way, and then when I automatically select the table cells.

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell! if tableView == self.jobLevelTableView { let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier", for: indexPath) as! CheckboxCell // for testing purposes let checked = true // I used M13Checkbox here, in case anybody was wondering cell.checkbox.setCheckState(checked ? .checked : .unchecked, animated: false) if checked { tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none) } // CULPRIT cell.selectionStyle = .none return cell } cell = UITableViewCell() return cell } 

When I set the highlight style on the storyboard (and removing the code equivalent), the problem disappeared!

Storyboard useful

+1
Jun 28 '17 at 8:37
source share

You can also try setting the separator inserts to 0. I did this and it solved the problem, but the trade-off is that you lose the nice view of the insert.

0
Oct 12 '13 at 2:19
source share

This problem exists for single cell selection.

Another solution is to reload the table view, select, and then deselect:

 self.selectedIndex = inIndexPath.row; [inTableView reloadData]; [inTableView selectRowAtIndexPath:inIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; [inTableView deselectRowAtIndexPath:inIndexPath animated:YES]; 

This eliminates the subtle graphical selection glitch that I saw in Mark's solution.

0
Oct 18 '13 at 2:13
source share

this solution will not help anyone who does not use backgroundView in their cells, in any case:

 - (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { [cell setBackgroundColor:[UIColor grayColor]]; } 

Thus, the annoying visual effect is greatly reduced without having to reload the table. grayColor course, you can change grayColor to anything that helps you improve the result in your case.

0
Nov 29 '13 at 12:17
source share

use this:

 - (BOOL) tableView: (UITableView *) tableView shouldHighlightRowAtIndexPath: (NSIndexPath *) indexPath
 {
     UITableViewCell * cell = (UITableViewCell *) [tableView cellForRowAtIndexPath: indexPath];
     UIView * selectionColor = [[UIView alloc] init];
     selectionColor.backgroundColor = [UIColor clearColor];
     cell.selectedBackgroundView = selectionColor;
     // 71
     UIView * separatorLineView = [[UIView alloc] initWithFrame: CGRectMake (0, 71, 320, 2)]; /// change size as you need, where - 71 - y coordinate, 320 - weight, 2 - height
   // separatorLineView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @ "divider_goriz.png"]]; // you can also put image here
     separatorLineView.backgroundColor = [UIColor redColor];
     [cell.selectedBackgroundView addSubview: separatorLineView];
     return YES;
 }
0
Dec 02 '13 at 19:54
source share

I have done this:

  • Add a new view in the cell content view.
  • Connect this from a cell as selectedBackgroundView.
  • Add a subtitle to the new selected background view. Set it to start 16px on the left and cover the rest of the width, be 1px high, 1px down from the top and have a background color of 90% white.

In my case, I didn’t want my lines to be shaded when I selected, so I left the selected background view transparent, but you can make it any color you like.

Also, I do not use autolayout, so just set my sizes accordingly. I assume that at startup you will need to set the appropriate restrictions.

For me, this completely resolved the problem (although I agree that it really looks like a bug in ios 7).

0
Jan 17 '14 at 13:02
source share

The solutions here did not help me. In most cases, it was suggested to remove the selection, but I wanted the cells to maintain the selected state. Therefore, the idea is to disable the default separator line and use your own dividing line. I tried this, but I had problems with this (you can read about it here ). The main problem was drawing a line in the accessorView . It only worked on iOS 8, but I also needed a solution for iOS 7.

My requirements:

  • Selection must be kept
  • The line should not disappear (especially when selecting a cell)
  • The separator line above the selected cell should also not disappear.

Especially the third problem arose because of the problems, since iOS uses some kind of smoothing effect to go to the UITableViewCell to the next. As I found out, this only happens on the iPad. It has a size of about one point in each direction (the current selected cell, the cell above), so that the line on the cell disappears even if it is drawn on the cell itself (and not on the one that was used by default). It does not matter if this line is on the cell above or on the selected cell. This special effect hides my lines.

The solution is as follows:

  • Use a backgroundView where you draw two lines: one at the top (+1 point in the y direction for the iPad and 0 points in the y direction for the iPhone) and one at the bottom. Thus, it is never covered by the effect of choice.
  • The created background view should be used only for the selected state ( cell.selectedBackgroundView = selectedBackground ). Separator line is enabled by default for other cells.

I have a working example with the C # code posted here , although you need to adapt it to your needs. Now my choice problems are gone!

0
Dec 09 '14 at 15:48
source share

Too interesting, I solved this problem. Add the following method call to the custom cell and set the color separator and frame. I will hide the cell separator and then adjust the view in the load separator in supervisor mode. The shock separator cell is selected when this problem is solved by friends.

 @interface MyCustomTableViewCell(){ UIView *customSeparatorView; CGFloat separatorHight; } @property (nonatomic,weak)UIView *originSeparatorView; @end -(void)setSeparatorWithInset:(UIEdgeInsets)insets{ if (customSeparatorView) { customSeparatorView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, self.originSeparatorView.height-insets.bottom - insets.top); self.originSeparatorView.hidden = YES; self.originSeparatorView.alpha = 0; }else{ for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) { UIView *subView = self.contentView.superview.subviews[i]; if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) { self.originSeparatorView = subView; subView.hidden = YES; subView.alpha = 0; subView.frame = CGRectMake(insets.left, insets.top,self.width - insets.left - insets.right, subView.height-insets.bottom - insets.top); customSeparatorView = [[subView superview] viewWithTag:separatorViewTag]; if (!customSeparatorView) { customSeparatorView = [[UIView alloc] initWithFrame:subView.frame]; customSeparatorView.tag = separatorViewTag; [[subView superview] addSubview:customSeparatorView]; customSeparatorView.backgroundColor = [subView backgroundColor]; } [[subView superview] bringSubviewToFront:customSeparatorView]; break; } } } } -(void)setSeparatorColorWithColor:(UIColor *)sepColor{ if (customSeparatorView) { customSeparatorView.backgroundColor = sepColor; self.originSeparatorView.hidden = YES; self.originSeparatorView.alpha = 0; }else { for (int i = ([self.contentView.superview.subviews count] - 1); i >= 0; i--) { UIView *subView = self.contentView.superview.subviews[i]; if ([NSStringFromClass(subView.class) hasSuffix:@"SeparatorView"]) { self.originSeparatorView = subView; if (sepColor) { subView.hidden = YES; subView.alpha = 0; subView.backgroundColor = sepColor; customSeparatorView = [[subView superview] viewWithTag:separatorViewTag]; if (!customSeparatorView) { customSeparatorView = [[UIView alloc] initWithFrame:subView.frame]; customSeparatorView.tag = separatorViewTag; [[subView superview] addSubview:customSeparatorView]; customSeparatorView.backgroundColor = [subView backgroundColor]; } [[subView superview] bringSubviewToFront:customSeparatorView]; } break; } } } } -(void)layoutSubviews{ [super layoutSubviews]; [self setSeparatorWithInset:UIEdgeInsetsMake(0, 0, 0, 0)]; [self setSeparatorColorWithColor:[UIColor colorWithRed:31/255.0 green:32/255.0f blue:35/255.0 alpha:0.2]]; } 
0
May 12 '15 at 7:06
source share

what solved the problem for me was reloading the data after beginUpdates and endUpdates:

  private func animateCellHeighChangeForTableView(tableView: UITableView, withDuration duration: Double) { UIView.animateWithDuration(duration) { () -> Void in tableView.beginUpdates(); tableView.endUpdates(); tableView.reloadData(); } } 
0
Jun 04 '16 at 3:50
source share

Pass it in your UITableViewCell class.

 override func layoutSubviews() { super.layoutSubviews() subviews.forEach { (view) in if type(of: view).description() == "_UITableViewCellSeparatorView" { view.alpha = 1.0 } } } 
0
Nov 30 '17 at 12:17
source share

I needed the following:

"When the user selects a row, the background color of the selection is transparent / white / whatever you can name, and the dividing lines do not disappear"

I also found a solution to solve the following problem:

"When I select a row in a table (a regular type table), I had a choice of color gray, and if I set cell.selectionStyle to none -> Separators between cells disappeared."

Xcode - version 9.2

Found the following solution:

  • in 'tableView (.... cellForRowAT ...)' let colorView = UIView(frame: CGRect(x: 0.0, y: 3.0, width: cell.frame.width, height: cell.frame.height - 1.0)) colorView.backgroundColor = UIColor.white UITableViewCellClass.appearance().selectedBackgroundView = colorView

UITableViewCellClass - your cell class prototype, it allows you to change the selection color to white

  1. in 'tableView (... didSelectRowAt)' cell.selectionStyle = .none

  2. in UITableViewCellClass (prototype cell class)

    override func layoutSubviews () {super.layoutSubviews ()

     subviews.forEach { (view) in if type(of: view).description() == "_UITableViewCellSeparatorView" { view.alpha = 1.0 } } 

    }

It allows you to save the selected line with a checkmark and all delimiters in place.

0
Mar 30 '18 at 7:42
source share

For those of you who are looking for a solution in Swift, this fixed the problem for me. In your cellForRowAtIndexPath method cellForRowAtIndexPath after calling dequeueReusableCellWithIdentifier you just need to set the selectionStyle cells to .None

Here is the code:

  override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell:TextTableViewCell = tableView!.dequeueReusableCellWithIdentifier("textCell", forIndexPath: indexPath) as! TextTableViewCell cell.selectionStyle = .None // This fixes the disappearing border line issue 
-2
Oct 08 '15 at 15:27
source share



All Articles