【问题标题】:How to fade items using reloadItems(at: [indexPath])如何使用 reloadItems 淡化项目(在:[indexPath])
【发布时间】:2020-01-26 05:30:09
【问题描述】:

我有一个包含uicollectionview 的视图控制器。每个collectionview 单元格都包含一个按钮,单击该按钮会在单元格中添加一个新标签。为了扩展每个单元格的高度,我调用了reloadItems(at: [indexPath])

不幸调用reloadItems(at: [indexPath]) 淡出旧标签并淡入新标签,如何防止任何标签淡出?

每次单击addLabel 按钮时,该错误变得更加明显:一个新标签淡入,但以前不可见的任何标签突然再次出现,而以前可见的任何标签又神奇地再次变为不可见。

reloadItems(at: [indexPath]) 似乎以不同方式切换每个新标签的 alpha。我想调整单元格的大小并向单元格添加新标签,而不会让任何标签消失。

这是我的代码:

视图控制器

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)
    }
  }
}

【问题讨论】:

    标签: ios swift uicollectionview uicollectionviewcell uicollectionviewlayout


    【解决方案1】:

    这是因为你为新标签设置了动画

    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 Self Sizing Cells with Auto Layout”中的建议,然后要么忘记动画的想法,要么实现自定义布局。

    【讨论】:

      【解决方案2】:

      我建议您阅读自调整大小的 UICollectionViewCells(例如 UICollectionView Self Sizing Cells with Auto Layout)和 UIStackView(例如 https://janthielemann.de/ios-development/self-sizing-uicollectionviewcells-ios-10-swift-3/)。

      您应该使用 UIStackView,限制单元格 contentView 的顶部和底部边缘。
      然后你可以将你的标签作为 managedSubviews 添加到你的 stackView 中。这将添加带有动画的标签。 使用自动调整大小的单元格,您不需要 reloadItems,它应该可以按预期工作。

      【讨论】:

      • 第二个链接中的方法看起来像是要走的路,但是它们继承了UICollectionViewLayout 而不是UIViewController。切换到UICollectionViewLayout 是使自定尺寸单元起作用的唯一方法吗?我其余代码的编写方式需要UIViewController 继承。
      • @newswiftcoder 不,UICollectionViewLayout 将附加到您的 UIViewController。 UICollectionView 使用 UICollectionViewLayout 实例来确定如何布局单元格。但是您不必创建自定义布局,恕我直言,这对您的问题来说有点太多了。你只需要在你的 Cell 中有一个 UIStackView,适当地限制在 contentView 中。在您的collectionView(...sizeForItem..) 方法中,尝试返回 UICollectionViewFlowLayout.automaticSize。在您的单元格中,将您的标签添加到新的 StackView。这应该可以解决问题。
      • 我设置collectionView(...sizeForItem..)返回UICollectionViewFlowLayout.automaticSize但得到错误:项目宽度必须小于UICollectionView的宽度减去部分插入左右值,减去内容插入左右值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      相关资源
      最近更新 更多