Как исчезать элементы, используя reloadItems (at: [indexPath]) - PullRequest
2 голосов
/ 26 января 2020

У меня есть контроллер представления, который содержит uicollectionview. Каждая ячейка коллекции содержит кнопку, которая при нажатии добавляет новую метку в ячейку. Чтобы увеличить высоту каждой ячейки, я звоню reloadItems(at: [indexPath]).

К сожалению, вызов reloadItems(at: [indexPath]) стирает старую метку и затухает в новой метке, как я могу предотвратить исчезновение любых меток?

Ошибка становится еще более очевидной каждый раз, когда я нажимаю кнопку addLabel: новая метка исчезает, но все предыдущие метки, которые не были видны, внезапно появляются снова, и любые метки, которые раньше были видимыми, волшебным образом становятся невидимыми снова ,

reloadItems(at: [indexPath]), кажется, переключает альфа каждой новой метки по-разному. Я хотел бы изменить размер и добавить новые метки в ячейку, чтобы метки не исчезали.

Вот мой код:

ViewController

class ViewController: UIViewController {

weak var collectionView: UICollectionView!
var expandedCellIdentifier = "ExpandableCell"

var cellWidth:CGFloat{
    return collectionView.frame.size.width
}
var expandedHeight : CGFloat = 200
var notExpandedHeight : CGFloat = 50    

//the first Int gives the row, the second Int gives the amount of labels in the row
var isExpanded = [Int:Int]()

override func viewDidLoad() {
    super.viewDidLoad()
    for i in 0..<4 {
        isExpanded[i] = 1
    }
  }
}


extension ViewController:UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return isExpanded.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: expandedCellIdentifier, for: indexPath) as! ExpandableCell
    cell.indexPath = indexPath
    cell.delegate = self
    cell.setupCell = "true"
    return cell

}
}

extension ViewController:UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    if isExpanded[indexPath.row]! > 1{

        let height = (collectionView.frame.width/10)
        let newHeight = height * CGFloat(isExpanded[indexPath.row]!)
        return CGSize(width: cellWidth, height: newHeight)

    }else{
        return CGSize(width: cellWidth, height: collectionView.frame.width/6 )
    }

  }

}

extension ViewController:ExpandedCellDeleg{
func topButtonTouched(indexPath: IndexPath) {
    isExpanded[indexPath.row] = isExpanded[indexPath.row]! + 1

    UIView.animate(withDuration: 0.8, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.9, options: UIView.AnimationOptions.curveEaseInOut, animations: {
        self.collectionView.reloadItems(at: [indexPath])
    }, completion: { success in
        print("success")
    })
  }
}

протокол

protocol ExpandedCellDeleg:NSObjectProtocol{
func topButtonTouched(indexPath:IndexPath)
}

ExpandableCell

class ExpandableCell: UICollectionViewCell {

weak var delegate:ExpandedCellDeleg?
public var amountOfIntervals:Int = 1

public var indexPath:IndexPath!

var setupCell: String? {
    didSet {
        print("cell should be setup!!")
    }
}

let ivAddLabel: UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.image = #imageLiteral(resourceName: "plus")
    imageView.tintColor = .black
    imageView.contentMode = .scaleToFill
    imageView.backgroundColor = UIColor.clear
    return imageView
}()

override init(frame: CGRect) {
    super.init(frame: .zero)

    contentView.addSubview(ivAddLabel)

    let name = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 18))
    name.center = CGPoint(x: Int(frame.width)/2 , y: 20)
    name.textAlignment = .center
    name.font = UIFont.systemFont(ofSize: 16)
    name.textColor = UIColor.black
    name.text = "Fred"
    contentView.addSubview(name)

    ivAddLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -14).isActive = true
    ivAddLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
    ivAddLabel.widthAnchor.constraint(equalToConstant: 20).isActive = true
    ivAddLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
    ivAddLabel.layer.masksToBounds = true
    ivAddLabel.isUserInteractionEnabled = true
    let addGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ivAddLabelSelected))
    ivAddLabel.addGestureRecognizer(addGestureRecognizer)
}
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
@objc func ivAddLabelSelected(){
    print("add button was tapped!")
    if let delegate = self.delegate{

        amountOfIntervals = amountOfIntervals + 1
        let height = (20*amountOfIntervals)

        let name = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 18))
        name.center = CGPoint(x: Int(frame.width)/2, y: height)
        name.textAlignment = .center
        name.font = UIFont.systemFont(ofSize: 16)
        name.textColor = UIColor.black
        name.text = "newFred"
        name.alpha = 0.0
        contentView.addSubview(name)
        UIView.animate(withDuration: 0.2, animations: { name.alpha = 1.0 })

        delegate.topButtonTouched(indexPath: indexPath)
    }
  }
}

Ответы [ 2 ]

2 голосов
/ 26 января 2020

Это потому, что вы анимируете новую метку

UIView.animate(withDuration: 0.2, animations: { name.alpha = 1.0 })

и параллельно перезагружаете ячейку, которая создает новую ячейку / повторно использует существующую и показывает ее, но также вы оборачиваете перезагрузку в блок анимации, который кажется странным и бесполезно:

UIView.animate(withDuration: 0.8, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.9, options: UIView.AnimationOptions.curveEaseInOut, animations: {
        self.collectionView.reloadItems(at: [indexPath])
    }, completion: { success in
        print("success")
    })

Вам нужно удалить обе анимации и просто перезагрузить ячейку. Если вам нужна хорошая анимация расширения ячеек, вам нужно реализовать макет коллекции, который будет обрабатывать все состояния - начало, промежуточный, конец анимации. Это сложно.

Попробуйте использовать предложенный в другом ответе «Ячейки самоконтроля UICollectionView с автоматической разметкой», если это не поможет, либо либо забыли идею анимации, либо внедрите пользовательскую разметку.

1 голос
/ 26 января 2020

Я бы посоветовал вам ознакомиться с саморазмерными UICollectionViewCells (например, UICollectionView Self Sizing Cells с автоматической разметкой ) и UIStackView (например, https://janthielemann.de/ios-development/self-sizing-uicollectionviewcells-ios-10-swift-3/).

Вы должны использовать UIStackView с ограничениями на верхний и нижний края ваших ячеек contentView.
Затем вы можете добавить свои метки в качестве управляемого представления в свой стековый вид. Это добавит метки с анимацией. С саморазмерной ячейкой вам не нужно reloadItems, и она должна работать так, как вы ожидаете.

...