How to change image to previous state if other row

2019-08-14 09:15发布

So I have dynamic tableview and each row have play image. If I select the row image will change to pause icon. But what if I select another row, I need the image on previously selected row to have play icon again. How to handle such functionality?

All I have is:

     class ViewController: UIViewController {
        var stations = [
        (stationIcon: "rr_icon", stationName: "Radio1", urlString: "http://.._320", isPlaying: false),
        (stationIcon: "mm_icon", stationName: "Record2", urlString: "http://../_320", isPlaying: false),
........]

         func playSelectedStation(indexPath: NSIndexPath) {
        let url = NSURL(string: stations[indexPath.row].urlString)!
        stations[indexPath.row].isPlaying = true
        avPlayer = AVPlayer(URL: url)
        avPlayer.play()
    }


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! RadioTableViewCell
            cell.playPause.image = stations[indexPath.row].isPlaying ? UIImage(named: "cellPause") : UIImage(named: "cellPlay")
            return cell
        }

        func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

            switch indexPath.row {
            playSelectedStation(indexPath)
        tableView.reloadData()

Radio Stations are changing without problem, having issue only with play/pause icon state

2条回答
我想做一个坏孩纸
2楼-- · 2019-08-14 09:23

You can achieve it by going through visible cells and disable play button in all of them except the one the user has just tapped on:

class PlayItem {
    // your code
    var isPlaying = false
}

class RadioTableViewCell: UITableViewCell {

    // your code ....

    func setup(item item: PlayItem) {
        image = item.isPlaying ? UIImage(named: "cellPause") : UIImage(named: "cellPlay")
    }
}

In your delegate:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! RadioTableViewCell
    let item = items[indexPath.row] // you may think of storing this array in some kind of view model
    cell.setup(item: item)
    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedCell = tableView.cellForRowAtIndexPath(indexPath) as! RadioTableViewCell
    let selectedItem = items[indexPath.row]
    selectedItem.isPlaying = !selectedItem.isPlaying

    for cell in tableView.visibleCells {
        guard let visibleCell = cell as? RadioTableViewCell else { return }
        let path = tableView.indexPathForCell(visibleCell)
        let item = items[path.row]
        item.isPlaying = visibleCell == selectedCell
        visibleCell.setup(item: item)
    }
}

UPDATE: I have updated my answer to store the playback state in item.

查看更多
姐就是有狂的资本
3楼-- · 2019-08-14 09:28

Use the MVC pattern instead of storing data in the view object or the global(view controller) scope. Then your life will be much easier.

I think each row should be backed by a model object. Say:

class PlayItem {
    ....
    var isPlaying = false
}

then your cellForRowAtIndexPath method:

let playItem = self.playItemArray[indexPath.row]
cell.imageView.image = playItem.isPlaying ? UIImage("cellPause") : UIImage("cellPlay")

then in your didSelectRowAtIndexPath method, change the selected item isPlaying = true and all the other items isPlaying = false, and call tableView.reloadData(). The table view will refresh all the cells to reflect their correct state.

查看更多
登录 后发表回答