Reputation: 2078
As below gif showed, in the specific row of tableView, the playing song's image(Just Dance.mp3) is changed to dynamic image.
My main question is how to achieve this effect in my App, to use a GIF image or other approach? Need advice here.
What effect I want to achieve:
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
}
}
===================================================================
Update my code according to ATV's answer, currently I use static image to set different state of playing cell. Well I get interested to this fancy CAShapeLayer
:), and I need time to learn about it then to set the dynamic image for the specific cell.
/ / / Model, 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
}
/// Update, finally I make it worked, to involve lottie-ios
library, and import it in CustomCell.swift, implement it in playAnimation()
, but the pity thing is that animation repeat mode is not working, the animation just repeat once even I set the loopMode. I will search what is wrong later.
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")
}
}
}
Upvotes: 2
Views: 654
Reputation: 367
"Is that a GIF image used or other dynamic image?" - You can choose any of the options below that is more preferable for you:
UIBezierPath
and CAShapeLayer
(some
examples)Changing of the cell's state:
//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
}
Upvotes: 1