Reputation: 309
I am working on a tableview with custom cells. I need to highlight current selected (active) cell by setting background color for the title label, which is an immediate subview of cell.contentView. My code logic is like this (revised for better understanding):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *previousActiveCell = [tableView cellForRowAtIndexPath:_indexPathActiveCell]; // previous selection
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath: indexPath]; // current selection
UILabel *labelpreviousActiveCellTitle = [previousActiveCell.contentView viewWithTag:SUBVIEW_TAG_TITLE_LABEL];
UILabel *labelSelectedCellTitle = [selectedCell.contentView viewWithTag:SUBVIEW_TAG_TITLE_LABEL];
labelpreviousActiveCellTitle.backgroundColor = [UIColor clearColor]; // remove highlighting from previous selection
labelSelectedCellTitle.backgroundColor = [UIColor redColor]; // highlighted
_indexPathActiveCell = indexPath; // update _indexPathActiveCell with current selection
}
The problem is, when a new cell is selected, the highlighting background color appears for a very short moment, about half a second, and then disappears. If I comment out the calling for deselectRowAtIndexPath,
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
the highlighting background color will retain. My guess is that deselectRowAtIndexPath remembers all the subviews' previous background color and when it recovers the cell from the shaded background, it changes all the subviews' background color back.
My workaround is adding a delay like this:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
labelpreviousActiveCellTitle.backgroundColor = [UIColor clearColor];
labelSelectedCellTitle.backgroundColor = [UIColor redColor];
});
and it works. Note that I also tried a shorter delay like 0.01 second which did not work.
Setting the delay time with a magic number is an unpleasant way. My question is, is there any better way to set the background color for cell's subviews in tableview's didSelectRowAtIndexPath delegate method? Thanks in advance.
Upvotes: 0
Views: 144
Reputation: 2149
Make a temporary variable which will hold the selected cell in your view controller.I am using a custom cell. It's not so important here though
var selectedCellIndex:IndexPath?
in your viewDidLoad initialize this like this.
selectedCellIndex = IndexPath.init(row: -1, section: 0)// first row starts with 0 you know.
in your cellForRowAtIndexPath function modify it like this.
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "chatCell", for: indexPath) as! sampleTableViewCell
if indexPath.row == selectedCellIndex?.row {
cell.label.backgroundColor = UIColor.green
}
else {
cell.label.backgroundColor = UIColor.clear
}
cell.selectionStyle = .none //For removing grey color while cell selection.
return cell
}
change your didSelectRowAtIndexPath like this.
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedCellIndex = indexPath
tableView.reloadRows(at: tableView.indexPathsForVisibleRows!, with: .none) //reload only visible cells. don't call reloadData it's expensive.
}
Here is the output:
Upvotes: 2
Reputation: 102
Have you tried creating a custom cell that inherits from UITableViewCell?
The custom cell would have a label as a public property so you can reference the label from your controller, without tagging.
Upvotes: 1