У меня есть пара строк, и у каждой строки есть состояние и состояния (Ожидание, выполняется, выполнено).Также у каждой строки есть заголовок, imageView, topLine и bottomLine.
В зависимости от состояния строки, мне нужно анимировать ход строки и изменить изображение в imageView с анимацией.
До сих пор я выполнял изменение изображения в imageView с анимацией, но это не идеально.Он показывает анимацию при прокрутке.Кроме того, я пробовал анимацию прохождения строки с помощью UIBezierPath, но безуспешно.Это колеблется при прокрутке. Образец изображения
Я хочу добиться, линия будет рисоваться с анимацией, и изображение будет меняться только тогда, когда линия анимируется в ячейке.Он не должен колебаться, пока мы прокручиваем tableView.
Некоторая ссылка кода
В cellForRowAtindexPath
let cell = tableview.dequeueReusableCell(withIdentifier: "AnimationTableViewCell") as? AnimationTableViewCell
// code block without animation. Only image animation done but its not perfect
/*switch indexPath.row {
case 0:
let firstIndex = 0
let nextIndex = 1
cell?.animateFrom(first: arrItem[firstIndex], to: arrItem[nextIndex])
case arrItem.count - 1:
let currentIndex = indexPath.row
let prevIndex = currentIndex - 1
cell?.animateFrom(previous: arrItem[prevIndex], to: arrItem[currentIndex])
default:
let currentIndex = indexPath.row
let prevIndex = currentIndex - 1
let nextIndex = currentIndex + 1
cell?.animate(previous: arrItem[prevIndex], current: arrItem[currentIndex], next: arrItem[nextIndex])
}
cell?.changeImageWithAnimation(arrItem[indexPath.row].state, row: indexPath.row)*/
// code block with improper animation
if (cell?.shapeLayer == nil) {
cell?.doAnimation(state: arrItem[indexPath.row].state, row: indexPath.row, isFirstTime: firstTime)
}
cell?.lblTitle.text = arrItem[indexPath.row].title
cell?.clipsToBounds = true
cell?.selectionStyle = .none
return cell!
в AnimationTableViewCell
func doAnimation(state: ProgressType, row: Int = 0, isFirstTime: Bool) {
NSLog("\(row)")
guard isFirstTime else {
return
}
// DispatchQueue.main.asyncAfter(deadline: <#T##DispatchTime#>, execute: <#T##() -> Void#>)
DispatchQueue.main.asyncAfter(deadline: (DispatchTime.now() + .seconds(row))) {
self.shapeLayer?.removeFromSuperlayer()
// create whatever path you want
let path = UIBezierPath()
path.move(to: CGPoint(x: self.lblTopLine.frame.origin.x, y: 0))
path.addLine(to: CGPoint(x: self.lblTopLine.frame.origin.x, y: 74))
path.addLine(to: CGPoint(x: self.lblTopLine.frame.origin.x, y: 148))
// create shape layer for that path
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
shapeLayer.strokeColor = state.color().cgColor
// shapeLayer.strokeColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1).cgColor
shapeLayer.lineWidth = 4
shapeLayer.path = path.cgPath
// animate it
self.layer.addSublayer(shapeLayer)
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 1
shapeLayer.add(animation, forKey: "MyAnimation")
// save shape layer
self.shapeLayer = shapeLayer
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
// self.lblTopLine.backgroundColor = state.color()
// self.lblBottomLine.backgroundColor = state.color()
// self.shapeLayer?.removeFromSuperlayer()
})
self.imgView.image = UIImage(named: "initial")
self.imgView.backgroundColor = UIColor.clear
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250), execute: {
UIView.animate(withDuration: 0.5, animations: {
self.imgView.backgroundColor = UIColor.red
})
UIView.transition(with: self.imgView, duration: 0.5, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
self.imgView.image = UIImage(named: "tick")
}, completion: nil)
})
}
}
Вы можете скачатьПример проекта от здесь .