You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为UITableView指定行单元格设置动态播放状态图像?

实现UITableView播放行的动态状态切换效果

最近开发音乐App时,需要实现这样的需求:

  • 歌曲播放时,对应UITableView行显示动态效果
  • 暂停播放时,动态效果停止
  • 切换到其他歌曲时,原播放行恢复显示专辑封面

下面是我从初始想法到最终实现的整个过程:

初始尝试:直接用GIF作为动态图

一开始我想直接用GIF图来实现播放时的动态效果,写了这段未测试的代码,但后来发现这种方式在cell复用场景下控制起来不够灵活,而且没法精准控制播放/暂停状态:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
    if resultSearchController.isActive {
        cell.addButton.tag = indexPath.row
        cell.songTitle.text = filteredTableData[indexPath.row].songName
        cell.songArtist.text = filteredTableData[indexPath.row].artistName
        cell.songArtwork.image = filteredTableData[indexPath.row].albumArtwork
        return cell
    } else {
        cell.addButton.tag = indexPath.row
        cell.songTitle.text = tableData[indexPath.row].songName
        cell.songArtist.text = tableData[indexPath.row].artistName
        cell.songArtwork.image = tableData[indexPath.row].albumArtwork
        return cell
    }
    // set image of specific tableView row cell to GIF image
    if indexPath.row == SongData.currentTrack {
        let image = UIImage(named: "playing-gif-image")
        cell.songArtwork.image = image
    } else {
        // do nothing
    }
}

改进方案:用静态状态区分播放状态

之后我转向用静态图标区分不同状态(播放/暂停/默认),同时计划后续学习CAShapeLayer来实现自定义动态效果。这个方案逻辑更清晰,也更容易控制状态切换:

1. 完善数据模型(SongData.swift)

首先在数据模型中添加播放状态枚举,以及控制全局播放状态的静态变量:

import UIKit
class SongData: NSObject, NSCoding {
    var songName: String
    var artistName: String
    var albumName: String
    var albumArtwork: UIImage
    var url: URL
    static var songList = [SongData]()
    static var shuffleSongList = [SongData]()
    static var currentTrack = 0
    static var showCurrentPlayingSong = false
    static var repeatSequence = "repeatList"
    static var isPlaying = false
    enum PlayingCellState {
        case nonState
        case playing
        case paused
    }
    init(songName: String, artistName: String, albumName: String, albumArtwork: UIImage, url: URL) {
        self.songName = songName
        self.artistName = artistName
        self.albumName = albumName
        self.albumArtwork = albumArtwork
        self.url = url
    }
    // NSCoding相关实现省略...
}

2. 自定义Cell添加状态配置方法(CustomCell.swift)

在自定义Cell中添加一个根据状态配置UI的方法,这样可以统一管理不同状态下的显示:

import UIKit
class CustomCell: UITableViewCell {
    @IBOutlet weak var songTitle: UILabel!
    @IBOutlet weak var songArtist: UILabel!
    @IBOutlet weak var songArtwork: UIImageView!
    @IBOutlet weak var addButton: UIButton!
    override func awakeFromNib() {
        super.awakeFromNib()
        songArtwork.layer.cornerRadius = 8.0
    }
    func config(forState state: SongData.PlayingCellState) {
        // 根据状态设置Cell显示
        switch state {
        case .nonState:
            print("nonState")
            // 恢复默认专辑封面显示
        case .playing:
            songArtwork.image = UIImage(named: "Play")
        case .paused:
            songArtwork.image = UIImage(named: "Pause")
        }
    }
}

3. 表格控制器中处理状态判断(TableViewController)

添加一个方法来判断每个Cell对应的状态,然后在cellForRowAt中调用Cell的配置方法:

// 判断Cell对应的播放状态
func stateForCell(at indexPath: IndexPath) -> SongData.PlayingCellState {
    // 首次打开列表且无歌曲播放时,返回默认状态
    if SongData.songList.count == 0 {
        return .nonState
    } else {
        if indexPath.row == SongData.currentTrack {
            return SongData.isPlaying ? .playing : .paused
        } else {
            return .nonState
        }
    }
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
    if resultSearchController.isActive {
        cell.addButton.tag = indexPath.row
        cell.songTitle.text = filteredTableData[indexPath.row].songName
        cell.songArtist.text = filteredTableData[indexPath.row].artistName
        cell.songArtwork.image = filteredTableData[indexPath.row].albumArtwork
    } else {
        cell.addButton.tag = indexPath.row
        cell.songTitle.text = tableData[indexPath.row].songName
        cell.songArtist.text = tableData[indexPath.row].artistName
        cell.songArtwork.image = tableData[indexPath.row].albumArtwork
    }
    // 配置Cell的播放状态
    cell.config(forState: stateForCell(at: indexPath))
    return cell
}

最终方案:用Lottie实现动态音频可视化效果

为了让播放状态的动态效果更生动,我引入了lottie-ios库来实现音频可视化动画,但目前遇到一个小问题:设置了循环模式后,动画仅播放一次,后续会排查具体原因。

更新后的CustomCell.swift代码

import UIKit
import Lottie
class CustomCell: UITableViewCell {
    @IBOutlet weak var songTitle: UILabel!
    @IBOutlet weak var songArtist: UILabel!
    @IBOutlet weak var songArtwork: UIImageView!
    @IBOutlet weak var view: UIView!
    @IBOutlet weak var addButton: UIButton!
    let animationView = AnimationView()
    override func awakeFromNib() {
        super.awakeFromNib()
        songArtwork.layer.cornerRadius = 8.0
    }
    func playAnimation(){
        let animation = Animation.named("366-equalizer-bounce")
        animationView.animation = animation
        // 这里遇到了问题:设置循环模式后动画只播放一次
        animationView.loopMode = LottieLoopMode.repeat(3600.0)
        animationView.play()
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        NSLayoutConstraint.activate([
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
    }
    func config(forState state: SongData.PlayingCellState) {
        // 根据状态设置Cell显示
        switch state {
        case .nonState:
            print("nonState")
            view.isHidden = true
        case .playing:
            view.isHidden = false
            playAnimation()
        case .paused:
            view.isHidden = false
            // 后续完善暂停时的显示逻辑
            // songArtwork.image = UIImage(named: "Pause")
        }
    }
}

内容的提问来源于stack exchange,提问作者Zhou Haibo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:16:26