skip to Main Content

I want to have this ring progress view (cocoa pod) inside collectionView Cells. When you tap on a cell, the progress should increase by 0.1 (0.0 = 0% Progress, 1.0 = 100% progress).

Unfortunately, it seems like it always creates a new progress view above the old one, because the shade of red is getting darker and you can see a second/third/.. ring. I have no idea how I can fix this.

This is my code: (Cell class and CollectionViewController Class)

    import UIKit

private let reuseIdentifier = "Cell"

class myCollectionViewController: UICollectionViewController {

    @IBOutlet var myCollectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        myCollectionView.reloadData()
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 7
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! myCollectionViewCell
    
        if(indexPath.item != 0){
            cell.setProgress(progress: 1 / Double(indexPath.item))
        }
        return cell
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! myCollectionViewCell
        cell.setProgress(progress: cell.getProgress() + 0.1)
        myCollectionView.reloadData()
    }
}



import UIKit
import MKRingProgressView

class myCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var ringView: UIView!
    let ringsize = 150
    var ringProgressView = RingProgressView()
    override func layoutSubviews() {
         ringProgressView = RingProgressView(frame: CGRect(x: 0, y: 0, width: ringsize, height: ringsize))
        ringProgressView.startColor = .red
        ringProgressView.endColor = .magenta
        ringProgressView.ringWidth = CGFloat(ringsize) * 0.15
        ringProgressView.progress = 0.0
        ringProgressView.shadowOpacity = 0.5
        ringView.addSubview(ringProgressView)
    }
}

extension myCollectionViewCell{
    func setProgress(progress: Double){
        UIView.animate(withDuration: 0.5){
            self.ringProgressView.progress = progress
        }
    }
    func getProgress() -> Double{
        return self.ringProgressView.progress
    }
}

This is what it looks like when launch (the progress it for testing at (1/indexpath.item):

screenshot when launch

And this is what it looks like when I TAP THE BOTTOM LEFT CICLE 1 TIME:

screenshot after tap 1x

I can see with the animation, that a second ring overlays the first ring on the bottom left circle with same progress. Somehow the other rings also changed… why? You can even see the second ring on some other circles. You can also see that the shade of the red went a little bit darker. When I tap multiple times, everything becomes completely (intensive) red.

Thanks for any help!

2

Answers


  1. Simple usage:

        override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            let cell = collectionView.cellForItem(at: indexPath) as! myCollectionViewCell
            cell.setProgress(progress: cell.getProgress() + 0.1)
        }
    

    you should not call like this:

        override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! myCollectionViewCell
            cell.setProgress(progress: cell.getProgress() + 0.1)
            myCollectionView.reloadData()
        }
    

    because of cell reuse mechanism,

    you call

    collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! myCollectionViewCell
    

    you get a cell of objects pool, namely a cell of newly created , or a cell created and not visible


    myCollectionView.reloadData()
    

    that’s worse, call this, just do resetting,

    because you do not maintain the data.

    Login or Signup to reply.
  2. You can use pattern mark & config

    in method didSelectItemAt , update the data

    in method cellForItemAt , update the UI, use myCollectionView.reloadData() to trigger

      var progressData = [IndexPath: Double]()
    
      override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! myCollectionViewCell
        
            
            if let val = progressData[indexPath]{
                 cell.setProgress(progress: val)
            }
            else{
                 var value = Double(0)
                 if(indexPath.item != 0){
                     value = 1 / Double(indexPath.item)
                 }
                 
                 progressData[indexPath] = value
                 cell.setProgress(progress: value)
            }
            
            return cell
        }
        
        override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            progressData[indexPath]! += 0.1
            myCollectionView.reloadData()
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search