Highlight TableView Cell's TextLabel text colour - ios

I am using a popover tableview in my project. I want to change the tableview cell's text colour from grey to red on selection. And i also want the highlighted color to remain red when the popover tableview is loaded next time like left menu selection. Need help to do this. I have provided the code for the popover tableview.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView === tableViewPopOver {
let cell = UITableViewCell(style: .Default, reuseIdentifier: nil)
cell.textLabel?.text = FeedFilter.allValues[indexPath.row].rawValue
if indexSelected == indexPath.row {
cell.textLabel?.textColor = UIColor.redColor()
} else {
cell.textLabel?.textColor = UIColor.lightGrayColor()
}
//cell.selectionStyle = .None
return cell
}
let cell = tableView.dequeueReusableCellWithIdentifier(kDreamFeedTableViewCell, forIndexPath: indexPath) as! DreamFeedTableViewCell
cell.selectionStyle = .None
let dream = self.arrayDreams[indexPath.row]
cell.dream = dream
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView === tableViewPopOver {
//tableViewPopOver?.cellForRowAtIndexPath(indexPath)?.textLabel?.highlightedTextColor = UIColor.redColor()
//selectedIndexPath = indexPath.row
let cell = tableView.cellForRowAtIndexPath(NSIndexPath.init(forRow: indexSelected, inSection: 0))
cell?.textLabel?.textColor = UIColor.lightGrayColor()
let cell2 = tableView.cellForRowAtIndexPath(indexPath)
cell2?.textLabel?.textColor = UIColor.redColor()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
indexSelected = indexPath.row
self.popover.dismiss()
NRLoader.showLoader()
self.searchDreams(true)
}
else { // dream feed tableview
tableView .deselectRowAtIndexPath(indexPath, animated: false)
let dream = self.arrayDreams[indexPath.row]
if !isValidUser(dream.user) {
return
}
if isCurrentUser(dream.user)
{
self.pushToUserDreamViewControllerForDream(dream)
}
else
{
tableView .deselectRowAtIndexPath(indexPath, animated: false)
self.pushToFeedDetailViewControllerForDream(dream)
}
}
}

I see a problem with your code relate to tableViewPopOver. If you set selection style is .None. You can't select cell.
With your problem I can suggest for you two way to resolve:
If you want use cell.textLabel?.highlightedTextColor you will have face a problem: background of cell will be grey or blue depend on style selection you select. If you can accept it. You can implement like this:
You create a variable to hold a cell selected. Maybe it is int value like var indexSelected = 3. And when you implement cellForRowAtIndexPath you should implement like this:
cell.textLabel?.text = FeedFilter.allValues[indexPath.row].rawValue
cell.textLabel?.highlightedTextColor = UIColor.redColor()
if indexPath.row == indexSelected {
tableView.selectRowAtIndexPath(indexPath, animated:true, scrollPosition: .None)
}
return cell
And in didSelectRowAtIndexPath you update indexSelected:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
indexSelected = indexPath.row //update selected row
}
If you don't want cell background change color. You can choose this way. You should create variable like the way above. But in cellForRowAtIndexPath you should implement:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")//init cell it depend on your way create cell
cell?.textLabel?.text = "Your text"
if indexSelected == indexPath.row {
cell?.textLabel?.textColor = UIColor.redColor()
} else {
cell?.textLabel?.textColor = UIColor.lightGrayColor()
}
return cell!
}
and in didSelectCellAtIndexPath you should implement:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(NSIndexPath.init(forRow: indexSelected, inSection: 0))
cell?.textLabel?.textColor = UIColor.lightGrayColor()
let cell2 = tableView.cellForRowAtIndexPath(indexPath)
cell2?.textLabel?.textColor = UIColor.redColor()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
indexSelected = indexPath.row //update selected row
}
Here Demo: Demo
Hope this help!

To change cell's text colour to red on selection you need to implement didSelectRowAtIndexPath and change the cell text Color to red, but it will not stay red when you open it the next time. to handle that you need to have a member variable selectedIndexPath. So it will be something like this
var selectedIndexPath:NSIndexPath!
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.textLabel?.highlightedTextColor = UIColor.redColor()
selectedIndexPath = indexPath
}
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.textLabel?.highlightedTextColor = UIColor.grayColor()
selectedIndexPath = nil
}
}
And to load the table next time with the selected cell red text colour you need to add this line in your cellForRowAtIndexPath
Cell
cell.textLabel?.highlightedTextColor = indexPath == selectedIndexPath ? UIColor.redColor() : UIColor.grayColor()
}

Related

Programmatically highlighting UITableViewCell in Swift

How do I programmatically highlight a table view cell?
I am using:
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
tableView.delegate?.tableView!(self.ordersTableView, didSelectRowAt: indexPath)
The problem I am having is that the cell IS being selected (all the actions specified in my didSelectRowAt are being performed) but the cell does now highlight. It doesn't appear selected.
What I am trying to achieve is like the Settings app on the iPad. You launch the app and see the "general" cell already selected and highlighted.
The cells highlight properly when touched by the user.
I have even tried overwriting the isSelected variable in my subclass of UITableViewCell.
Ok turns out it was a problem with background tasks. The cells were loaded again after I selected them and that's why the selection wasn't visible.
Note: Your question title says, you have a query with cell highlight and your question description says, you have a problem with cell selection. Both are different events.
Here is an answer, how you can manage (set color) on tableview row (cell) selection:
// make sure your tableview row selection is enabled
yourTableViewInstance.allowsSelection = true
// handle highlighted background in data source method also
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "textview") as! YourTableViewCell
cell.contentView.backgroundColor = cell.isSelected ? UIColor.red : UIColor.gray
return cell
}
// didSelectRowAtIndexPath - change background color
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? YourTableViewCell {
cell.contentView.backgroundColor = UIColor.red
}
}
// didDeselectRowAtIndexPath - change background color
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? YourTableViewCell {
cell.contentView.backgroundColor = UIColor.gray
}
}
Try this:-
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
var selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
selectedCell.contentView.backgroundColor = UIColor.redColor()
}
Here is another option to handle cell background selection
class YourTableViewCell: UITableViewCell {
// override cell selection
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if self.selectedBackgroundView == nil {
let bgView = UIView()
self.selectedBackgroundView = bgView
}
self.selectedBackgroundView?.backgroundColor = selected ? UIColor.red : UIColor.gray
}
}
// enable row/cell selection
yourTableViewInstance.allowsSelection = true
// handle highlighted background in data source method also
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "textview") as! YourTableViewCell
if self.selectedBackgroundView == nil {
let bgView = UIView()
self.selectedBackgroundView = bgView
}
self.selectedBackgroundView?.backgroundColor = selected ? UIColor.red : UIColor.gray
return cell
}

indexPathForSelectedRow returns nil although I have a cell programmatically selected

I have a UITableView which I load with some application settings. I need the table to be single-select, and since the table holds settings there might be a chance some cell will be programmatically selected based on the setting enabled status.
Currently, I'm experiencing a weird behaviour where if I programmatically select a cell then indexPathForSelectedRow returns nil (when it should return the index for the cell I selected), thus when I tap on a second cell (to change the currenty selected setting) I end up with two cells selected (even when I set allowMultipleSelection to false in my tableView object).
Here's my code:
override func viewDidLoad() {
tableView.allowsMultipleSelection = false
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("myCell")
if let cell = cell {
// tableObject is an array containing settings model
let row = tableObject[indexPath.row]
cell.textLabel!.text = row.settingValue
if row.selected {
cell.setSelected(true, animated: false)
cell.accessoryType = .Checkmark
}
cell.tag = row.id
}
return cell!
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
// oldIndex is always nil for the cell I called setSelected in cellForRowAtIndexPath
if let oldIndex = tableView.indexPathForSelectedRow {
if let oldCell = tableView.cellForRowAtIndexPath(oldIndex) {
tableView.deselectRowAtIndexPath(oldIndex, animated: true)
oldCell.accessoryType = .None
}
}
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.setSelected(true, animated: true)
cell.accessoryType = .Checkmark
}
return indexPath
}
override func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
return indexPath
}
Any idea how I can always have only one cell selected at a time?
Thanks!
Just in case someone else comes across this same behaviour, it seems that selecting the cell through cell.setSelected() it's not the same as invoking tableView.selectRowAtIndexPath() method. Selecting the row with the latest does the job perfectly and solves the issue.
Note that calling tableView.reloadData() resets the tableView.indexPathForSelectedRow to nil.
here how you can accomplish table view single selection through tableView.indexPathForSelectedRow :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.accessoryType = tableView.indexPathForSelectedRow == indexPath ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if let visiblePaths = tableView.indexPathsForVisibleRows
{
for visibleIndexPath in visiblePaths
{
let cell = tableView.cellForRow(at: visibleIndexPath)
if visibleIndexPath == indexPath
{
cell?.accessoryType = .checkmark
}
else
{
cell?.accessoryType = .none
}
}
}
}
Create an array like
var arrSelectCell = [NSIndexPath]()
And do the code at didSelectRowAtIndexPath like following:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if arrSelectCell.contains(indexPath) {
if let oldCell = tableView.cellForRowAtIndexPath(indexPath) {
if let index = arrSelectCell.indexOf(indexPath) {
arrSelectCell.removeAtIndex(index)
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
oldCell.accessoryType = .None
}
}
else
{
arrSelectCell.append(indexPath)
if let selectCell = tableView.cellForRowAtIndexPath(indexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
selectCell.accessoryType = .Checkmark
}
}
and also dont forget to set a code in cellForRowAtIndexPath to check already checked and unchecked cell maintain after reuse cell also. So need to few code you need to write as following.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("serchCell", forIndexPath: indexPath) as! SearchTableViewCell
if arrSelectCell.contains(indexPath)
{
cell.accessoryType = .Checkmark
}
else
{
cell.accessoryType = .None
}
return cell
}

Adding Accessory Type moves Label in UITableViewCell

I am trying to create something like a radio button; however, I am using a UITableView. I have the following code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .Default, reuseIdentifier: "sortcell")
if indexPath.row == 0 {
cell.textLabel?.text = "Student"
} else {
cell.textLabel?.text = "Teacher"
}
cell.textLabel?.textAlignment = .Center
cell.textLabel?.font = getFont(17.5)
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
var selectedIndexPath = 10
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selected = true
if indexPath.row == 0 {
sort = "Student"
let cell = sortTable.cellForRowAtIndexPath(indexPath)
cell?.accessoryType = .Checkmark
let otherIndexPath = NSIndexPath(forRow: 1, inSection: 0)
let otherCell = sortTable.cellForRowAtIndexPath(otherIndexPath)
otherCell?.accessoryType = .None
} else {
sort = "Teacher"
let cell = sortTable.cellForRowAtIndexPath(indexPath)
cell?.accessoryType = .Checkmark
let otherIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let otherCell = sortTable.cellForRowAtIndexPath(otherIndexPath)
otherCell?.accessoryType = .None
}
sortTable.deselectRowAtIndexPath(indexPath, animated: true)
}
This allows the user to switch between choosing whether he or she is a student or a teacher. However, when the accessoryType is added, the text label moves slightly, as shown:
Default:
When tapped:
How should I resolve this? I would like the text label to stay in the same place instead of shifting towards the left. Thanks for your help.
Try setting textLabel.textAlignment to .Left
I think it is because the Check Mark pushes the view to left. You may need to customised your cell's view

Swift. Change Color of Custom Tableview Cell Label when selected

I have a Custom Tableview cell in swift and in that cell a label.
I want to be able to change the label when you select a cell.
How can I reference my custom UITableviewCell label in didSelectRowAtIndexPath
In Objective C to reference my custom cell in didSelectRowAtIndexPath I would use the following:
MPSurveyTableViewCell *cell = (MPSurveyTableViewCell *)[tableViewcellForRowAtIndexPath:indexPath];
cell.customLabel.TextColor = [UIColor redColor];
What must I do in swift to achieve the same result?
You just need to translate the same code to Swift.
var myCell = tableView.cellForRowAtIndexPath(indexPath) as! MPSurveyTableViewCell
myCell.customLabel.textColor = UIColor.redColor()
The Above Answers Are Incomplete
Because a UITableView reuses cells you need to check if the cells are selected and adjust the color appropriately in cellForRowAtIndexPath. There may be typos, but this is the complete answer:
func tableView(tableView: UICollectionView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifierHere", forIndexPath: indexPath) as! MPSurveyTableViewCell
// setup your cell normally
// then adjust the color for cells since they will be reused
if cell.selected {
cell.customLabel.textColor = UIColor.redColor()
} else {
// change color back to whatever it was
cell.customLabel.textColor = UIColor.blackColor()
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! MPSurveyTableViewCell
cell.customLabel.textColor = UIColor.redColor()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
func tableView(tableView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! MPSurveyTableViewCell
// change color back to whatever it was
cell.customLabel.textColor = UIColor.blackColor()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
swift 3 xcode 8
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let Cell = tableView.cellForRow(at: indexPath)
Cell?.textLabel?.textColor = UIColor.red // for text color
Cell?.backgroundColor = UIColor.red // for cell background color
}
why not use setSelected in UITableViewCell subclass?
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
customLabel.textColor = selected ? UIColor.red : UIColor.black
}
or if you want it to go back to deselected color after a specific amount of time:
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if selected {
customLabel.textColor = UIColor.red
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [weak self] in
self?.customLabel.textColor = UIColor.black
}
}
}
Then just set your cell selectionStyle = .none
Try this,
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
var Cell = tableView.cellForRowAtIndexPath(indexPath) as! MPSurveyTableViewCell
Cell. customLabel.textColor = UIColor. redColor()
}
let CellObject = tableView.dequeueReusableCell(withIdentifier: "your cell identifier name") as! MPSurveyTableViewCell
CellObject.customLabel.textColor = UIColor.red

UI table view cell check marks repeating swift

My when a table cell is checked and you scroll down a check mark is repeated.
I know this is due to cell reuse, but don't know how to fix it.
function to populate table
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let item = self.myEvents[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("row", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = self.myEvents[indexPath.row]
return cell
}
//function to make the table checkable
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("indexpath: \(indexPath)")
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
let text = cell.textLabel!.text
if cell.accessoryType == UITableViewCellAccessoryType.None {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
//let text = cell.textLabel!.text
if(checkedEvents[0] == ""){
checkedEvents[0] = text!
}else{
checkedEvents.append(text!)
}
} else {
cell.accessoryType = UITableViewCellAccessoryType.None
var index = 0
for event in checkedEvents{
if event == text{
self.checkedEvents.removeAtIndex(index)
index++
}
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
First, you need to store the number of the selected row somewhere. How about self.selectedRowNumber?
var selectedRowNumber: Int? = nil
Set this when the user selects a row (short version):
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cell.accessoryType = .Checkmark
self.selectedRowNumber = indexPath.row
// You'll also need some code here to loop through all the other visible cells and remove the checkmark from any cells that aren't this one.
}
Now modify your -tableView:cellForRowAtIndexPath: method to clear the accessory if it's not the selected row, or add it if it is:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("row", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = self.myEvents[indexPath.row]
cell.accessoryType = .None
if let selectedRowNumber = self.selectedRowNumber {
if indexPath.row == selectedRowNumber {
cell.accessoryType = .Checkmark
}
}
return cell
}
This code was written here in the browser, and may need some fixes to compile.
If you want only one selection, put tableView.reloadData() in your didSelectRowAtIndexPath function

Resources