Uitableviewcell Checkmark to Be Toggled on and Off When Tapped

UITableViewCell checkmark to be toggled on and off when tapped

Swift > 3.0

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark

}
}

I solved by using two Swift functions: the didSelectRowAtIndexPath and the didDeselectRowAtIndexPath.

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .None
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = .Checkmark

}
}

To make this work properly, add a line of code to your cellForRowAtIndexPath function to select a row when the table view is drawn on the screen, otherwise the didDeselectRowAtIndexPath will not be called the first time you select another row. Like so:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellData", forIndexPath: indexPath)
if (some condition to initially checkmark a row)
cell.accessoryType = .Checkmark
tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.Bottom)
} else {
cell.accessoryType = .None
}

return cell
}

Swift: Toggling checkmark to ON for last selected cell only - not working

First tell your tableview it can only select one cell at a time:

override func viewDidLoad() {
super.viewDidLoad()

self.tableView.allowsMultipleSelection = false
}

Then, let's analyse your code, you're getting the section at which the present cell is being selected and calculating the number of rows in that specific section. You iterate on the rows of that section and checking if you have a cell at the given indexPath (I guess it always evaluates to true because you always have a cell at that indexPath, you didn't put a condition depending on the value of your for-loop). Then you tell the cell to have a checkmark if the row in the for-loop equals the row of the cell being currently selected by the user.
As your function is written, there is no reason why only the last in the section would get the checkmark, but you overcomplicated the matter.

Your cell is drawn in the following method and so should the accessory initially.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCell", for: indexPath)

cell.textLabel?.text = "your text"

cell.accessoryType = cell.isSelected ? .checkmark : .none
// cell.selectionStyle = .none if you want to avoid the cell being highlighted on selection then uncomment

return cell
}

Then you can just say that the accessory type should be .checkmark in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) and .none in tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath).Here is how to do it and you should be good, if not let me know and I can edit again.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .checkmark
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .none
}

Selecting TableView Cell Activates Checkmark in Rows in Multiple Sections

use data store for save checkmarks like this:

var selectedIngredients: Set<IndexPath> = [] // use set for unique save

then didSelect callBack:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if self.selectedIngredients.contains(indexPath) {
self.selectedIngredients.remove(indexPath)

} else {
self.selectedIngredients.insert(indexPath)
}

self.tableView.reloadData()
}

after reload in CellForRow:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients.contains(indexPath) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}

If you want it to have only one Row contain checkmark:

var selectedIngredients: IndexPath? = nil

and didSelect CallBack:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
self.selectedIngredients = indexPath
}

and finally:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients == indexPath {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}

UITableViewCell checkmark change on select


  1. Keep a property in your view controller called selectedRow, which represents the index of a row that represents the checked item in a table section.

  2. In your view controller's -tableView:cellForRowAtIndexPath: delegate method, set the accessoryType of the cell to UITableViewCellAccessoryCheckmark if the cell's indexPath.row equals the selectedRow value. Otherwise, set it to UITableViewCellAccessoryNone.

  3. In your view controller's -tableView:didSelectRowAtIndexPath: delegate method, set the selectedRow value to the indexPath.row that is selected, e.g.: self.selectedRow = indexPath.row

Want accessory checkmark to show only when tapped on the right

Instead of the built-in checkmark accessory type, why not provide, as accessory view, an actual button that the user can tap and that can display the checkmark? The button might, for example, display as an empty circle normally and as a circle with a checkmark in it when the user taps it.

Otherwise, you're expecting the user to guess at an obscure interface, whereas, this way, it's perfectly obvious that you tap here to mark the task as done.

Example:

Sample Image

To accomplish that, I created a button subclass and set the accessoryView of each cell to an instance of it:

class CheckButton : UIButton {
convenience init() {
self.init(frame:CGRect.init(x: 0, y: 0, width: 20, height: 20))
self.layer.borderWidth = 2
self.layer.cornerRadius = 10
self.titleLabel?.font = UIFont(name:"Georgia", size:10)
self.setTitleColor(.black, for: .normal)
self.check(false)
}
func check(_ yn:Bool) {
self.setTitle(yn ? "✔" : "", for: .normal)
}
override init(frame:CGRect) {
super.init(frame:frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

The title of the button can be the empty string or a checkmark character, thus giving the effect you see when the button is tapped. This code comes from cellForRowAt::

    if cell.accessoryView == nil {
let cb = CheckButton()
cb.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
cell.accessoryView = cb
}
let cb = cell.accessoryView as! CheckButton
cb.check(self.rowChecked[indexPath.row])

(where rowChecked is an array of Bool).

Swift | UIViewTable changes checkmark when scrolled off screen

The error occurs because you toggle the checked state always in configureCheckmark. So whenever cellForRow is called for this row the state is toggled.

Actually an extra method configureCheckmark is not needed. Put the line to set the checkmark in cellForRow but don't change the state.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
let item = todoList.items[indexPath.row]
configureText(for: cell, with: item)
cell.accessoryType = item.checked ? .checkmark : .none

return cell
}

In didSelectRowAt toggle checked in the model and reload the row

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
todoList.items[indexPath.row].checked.toggle()
tableView.reloadRows(at: [indexPath], with: .none)
}

The method toggleChecked() in ChecklistItem is redundant, too. There is a toggle() method in Bool.

And consider to use structs rather than classes.

UITableviewCell - Clicking on empty checkmark circle in edit mode does not select cell

The problem ended up being that I was setting a backgroundView on my custom table cell and that was preventing the touches from getting to the right target.



Related Topics



Leave a reply



Submit