Want accessory checkmark to show only when tapped on the right

好久不见. 提交于 2020-01-17 07:01:33

问题


I have a TableView with cells that when pressed anywhere in the cell, it adds a checkmark on the right. I only want the checkmark to show up if the cell is tapped on the right side. Here's the pertinent section of code from the TableViewController:

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

        let task = tasks[indexPath.row]
            cell.task = task


        if task.completed {
            cell.accessoryType = UITableViewCellAccessoryType.checkmark;
        } else {
            cell.accessoryType = UITableViewCellAccessoryType.none;
        }

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)

        var tappedItem = tasks[indexPath.row] as Task
        tappedItem.completed = !tappedItem.completed
        tasks[indexPath.row] = tappedItem

        tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
    }

}

Is there a simple way to do that, or to do it using storyboard? My Swift skills leave a LOT to be desired. Any help would be appreciated! Thank you!


回答1:


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:

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).




回答2:


You will have to define your own accessory button, and handle its own clicks.

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

    let task = tasks[indexPath.row]
        cell.task = task

    let checkButton = UIButtonSubclass()
    ...configure button with your circle and check images and a 'selected property'...
    checkButton.addTarget(self, action:#selector(buttonTapped(_:forEvent:)), for: .touchUpInside)
    cell.accessoryView = checkButton
    checkButton.selected = task.completed //... this should toggle its state...

    return cell
}

func buttonTapped(_ target:UIButton, forEvent event: UIEvent) {
    guard let touch = event.allTouches?.first else { return }
    let point = touch.location(in: self.tableview)
    let indexPath = self.tableview.indexPathForRow(at: point)
    if let task = tasks[indexPath.row] {
        task.completed = !task.completed
    }
    tableView.reloadData()   //could also just reload the row you tapped
}

Though, it has been noted that using tags to detect which row was tapped is dangerous if you start to delete rows. You can read more here https://stackoverflow.com/a/9274863/1189470

EDITTED Removed the reference to tags per @matt



来源:https://stackoverflow.com/questions/43035765/want-accessory-checkmark-to-show-only-when-tapped-on-the-right

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!