How can I make Shimmer Animation like react-loading-skeleton in iOS

2.3k Views Asked by At

I want to an Shimmer animation like this: https://gph.is/g/amWgbvj. (This one created by using library: https://github.com/dvtng/react-loading-skeleton in WebApp)

I tried to use GradientLayer with opacity to create Shimmer animation through all subviews:

gradientLayer.colors = [Colors.tokenDark20.cgColor, Colors.tokenDark10.cgColor, Colors.tokenDark20.cgColor]
gradientLayer.opacity = 0.5

But I got the animation: https://gph.is/g/4L3K01P.

More effort:

I tried to use the library: https://github.com/gonzalonunez/Skeleton, tried to chain animation from left to right, but I cant make the same length of gradient shape for all subview:

extension ShimmerExampleCell: SkeletonOwner {
    var gradientLayers: [CAGradientLayer] {
        return [imagePlaceholderView.gradientLayer, titlePlaceholderView.gradientLayer, subtitlePlaceholderView.gradientLayer]
    }
    func slide(to dir: SkeletonDirection, group: ((CAAnimationGroup) -> Void) = { _ in }) {
        imagePlaceholderView.gradientLayer.slide(to: .right) { (animationGroup) in
            animationGroup.beginTime = 0
        }
        
        titlePlaceholderView.gradientLayer.slide(to: .right) { (animationGroup) in
            animationGroup.beginTime = 1.1
            subtitlePlaceholderView.gradientLayer.add(animationGroup, forKey:  CAGradientLayer.kSlidingAnimationKey)
        }
    }
}

I got the animation in here: https://gph.is/g/ZPgPlXV

am I wrong to approach the way to make the Shimmer animation?

Help me please! Thank you in advance!

2

There are 2 best solutions below

1
On

You can try to use library SkeletonView; it should help you easily implement shimmer animation wherever you want.

0
On

View Controller:

class ViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!

var data: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
    tableView.delegate = self
    tableView.dataSource = self
    
    for value in 0..<20 {
        self.data.append("\(value) data")
        self.tableView.reloadData() 
    }
}

Extension Of ViewController:

extension ViewController: UITableViewDelegate, UITableViewDataSource {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return data.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
    cell.labelName.text = data[indexPath.row]
    return cell
}

UITableViewCell: Here I set the show or hide status for SkeletonView

class TableViewCell: UITableViewCell {

@IBOutlet weak var labelName: UILabel!
@IBOutlet weak var imgView: UIImageView!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    
    let views = [labelName, imgView]
    views.forEach {$0?.showHideSkeletonView(show: true)}
    
    DispatchQueue.main.asyncAfter(deadline: .now()+3) { 
        views.forEach {$0?.showHideSkeletonView(show: false)}
    }
}

ConfigSkeleton: Here I add a function for setup, animation and color for my skeletonView.

import SkeletonView

extension UIView {

   func setSkeletonView() {
        self.isSkeletonable = true
   }

    func showHideSkeletonView(show: Bool) {
        if show {
            let gradient = SkeletonGradient(baseColor: UIColor.clouds)
            let animation = SkeletonAnimationBuilder().makeSlidingAnimation(withDirection: .topLeftBottomRight)
            self.showAnimatedGradientSkeleton(usingGradient: gradient, animation: animation)
        } else {
            self.hideSkeleton()
        }
    }