【问题标题】:How to set specific row cell's image of tableView to dynamic image如何将tableView的特定行单元格的图像设置为动态图像
【发布时间】:2019-10-09 11:29:59
【问题描述】:

如下图gif所示,在tableView的特定行中,播放歌曲的图片(Just Dance.mp3)变成了动态图片。

我的主要问题是如何在我的应用程序中实现这种效果,使用 GIF 图片或其他方法?在这里需要建议。

我想达到什么效果:

  1. 播放歌曲时,特定行单元格的图像变为动态图像。 (主要问题
  2. 如果歌曲暂停,则该动态图像停止播放。
  3. when another song is selected to play, the previous song's(cell) image is resume to its album artwork.

这是我的 snip 代码,我还没有测试它,因为我不确定是否应该使用 GIF 或其他方法。

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
        }
    }

================================================ =====================

根据 ATV 的回答更新我的代码,目前我使用静态图像来设置不同的播放单元状态。嗯,我对这个花哨的CAShapeLayer:) 很感兴趣,我需要时间来了解它,然后为特定的单元格设置动态图像。

///模型,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
    } 
...
}

///CustomCell.swift

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) {
        // setup your cell depends on state
        switch state {
        case .nonState:
            print("nonState") //update cell to default state
        case .playing:
            songArtwork.image = UIImage(named: "Play")
        case .paused:
            songArtwork.image = UIImage(named: "Pause")
        }
    }
}

///TableViewController

 // use for track cell state, for playing dynamic image usage
    func stateForCell(at indexPath: IndexPath) -> SongData.PlayingCellState {
        // when firstly open the tab song list/app(with no song played), do not attach playing state image
        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
            // 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
        }

        cell.config(forState: stateForCell(at: indexPath))
        return cell
    }

/// 更新,终于搞定了,涉及到lottie-ios库,并在CustomCell.swift中导入,在playAnimation()中实现,可惜动画重复模式不起作用,即使我设置了循环模式,动画也只会重复一次。有什么问题我稍后会搜索。

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
        // weird thing is that animation repeat is not working here...
        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) {

        // setup your cell depends on state
        switch state {
        case .nonState:
            print("nonState")
            view.isHidden = true
        case .playing:
            view.isHidden = false
            playAnimation()
        case .paused:
            view.isHidden = false
            // to set this latter 
            // songArtwork.image = UIImage(named: "Pause")
        }
    }
}

【问题讨论】:

  • 您可以在模型中添加 1 个标志,例如 isCurrentlyPlay,一旦用户点击任意行播放歌曲,您只需将上述标志设置为 true 和一旦用户再次点击同一行,然后将其设为false,反之亦然,您可以根据此标志更改图像。如果您打算实施此操作,请取消选择所有数据标志,请点击此链接:stackoverflow.com/questions/46717778/…
  • @Kuldeep 问题表述不正确,但似乎有一部分是关于“如何实现 GIF 图像?”另一个“如何使用UITableViewCell 实现播放/暂停视图更新?” @ChuckZHB,如果我弄错了,请纠正我。此外,您关于添加布尔标志 isCurrentlyPlay 的建议并不是很简单,因为 Cell 的状态应该存储在视图之外。
  • @ATV,对不起,我昨天很忙。我的主要问题是如何实现上面的截图显示效果。可以是 GIF 还是其他方式?需要建议。接下来是暂停/播放tableView中的动态图像,但首先我需要知道如何在我的App中实现该效果。
  • @Kuldeep,是的,我的模型类中有一个isPlaying 标志。我在这个问题上的表达可能不是那么准确。我的主要问题是如何实现上面的截图显示效果。我会更新我的问题。

标签: ios swift uiimageview tableview animated-gif


【解决方案1】:
  1. 为了实施:

“这是使用的 GIF 图像还是其他动态图像?” - 您可以选择以下任何更适合您的选项:

  • 您可以使用 GIF 图片 (the similar question)
  • 你甚至可以 使用UIBezierPathCAShapeLayer (some examples) 绘制它
  • 或者使用lottie-ios库,它可以与Adobe After Effects动画一起使用(例如你可以使用this

  1. 细胞状态的改变:

    //e.g. add it to your presenter or wherever you are storing info about `currentTrack`
    ...
    enum PlayingCellState {
        case default
        case playing
        case paused
        ...
    }
    ...
    func stateForCell(at indexPath: IndexPath) -> PlayingCellState {
        if indexPath.row == SongData.currentTrack {
            return isPlaying? .playing : .paused
        } else {
            return .default
        } 
    }
    
    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
        }
    
        cell.config(forState: stateForCell(at: indexPath)
    }
    
    //add to your CustomCell 
    func config(forState state: PlayingCellState) {
    // setup your cell depends on state
    }
    

【讨论】:

  • 这就是我需要的!特别是关于UIBezierPathCAShapeLayer,它们看起来很漂亮,就像你的例子一样。我相应地更新了我的代码,它可以工作,并且最好将代码分别放在 CustomCell 和 Model 中以使可重用变得容易。
  • @ChuckZHB 我已经更新了我的答案并添加了一个库 - 这可以节省大量时间并获得漂亮的结果
  • 感谢我在我的项目中安装了 lottie-ios 库并将一些 json 动画文件也复制到其中。那么我应该如何创建动画 ImageView 呢?要创建一个 Swift 文件来实现动画或其他?
  • @ChuckZHB 他们在repo 中有一个示例项目,您可以使用任何类似的examples。简单说一下 - 你应该使用LOTAnimationView 而不是UIImageView。顺便说一句,如果答案有用,请不要忘记投票并将其标记为完成?
  • 好吧,这个例子很简单,但在我的情况下,我需要为大部分单元格的图像使用UIImageView,并且只有一个特定的单元格需要 AnimationView,问题是如何连接@ 987654335@这个AnimationView,需要一些提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-29
相关资源
最近更新 更多