如何实现可以显示图像或作为输入属性提供的自定义 UIView 的 CollectionViewCell?

Posted

技术标签:

【中文标题】如何实现可以显示图像或作为输入属性提供的自定义 UIView 的 CollectionViewCell?【英文标题】:How to implement a CollectionViewCell that can either display an image or a custom UIView provided as input property? 【发布时间】:2017-01-18 20:36:50 【问题描述】:

我有一个collectionView 单元格,它应该显示一个图像或一个生成为自定义UIView 的图标(比如说IconView)。 目前,我通过将UIImageViewIconView 作为子视图添加到容器视图来实现这一点。

当提供图像时,UIImageView 的图像属性会简单地更新。当提供新的IconView 时,它当前总是作为子视图添加到容器视图中。因此,在添加之前,首先检查IconView是否已经添加,如果已经添加,则删除。

虽然这个实现有效,但它不是很优雅,而且似乎效率不高,因为当行数增加时会导致滚动问题。

是否有更好(更有效)的方法来为单个 CollectionViewCell 实现这一点?

class CustomCell: UICollectionViewCell 

    internal var image: UIImage? 
        didSet 
            self.imageView.image = image!
        
    

    internal var iconView: IconView? 
        didSet 
            if !(self.iconContainerView.subviews.flatMap $0 as? IconView.isEmpty) 
                self.iconView!.removeFromSuperview()
            
            self.iconView!.translatesAutoresizingMaskIntoConstraints = false
            self.iconContainerView.addSubview(self.iconView!)
            self.image = nil            
        
    

    fileprivate var imageView: UIImageView!
    fileprivate var iconContainerView: UIView!
    fileprivate var layoutConstraints = [NSLayoutConstraint]()

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

        // ContainerView
        self.iconContainerView = UIView()
        self.iconContainerView.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(self.iconContainerView)

        // ImageView
        self.imageView = UIImageView()
        self.imageView.translatesAutoresizingMaskIntoConstraints = false
        self.iconContainerView.addSubview(self.imageView)
    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    override func layoutSubviews() 
        super.layoutSubviews()

        self.iconContainerView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor).isActive = true
        self.iconContainerView.widthAnchor.constraint(equalToConstant: 60).isActive = true
        self.iconContainerView.heightAnchor.constraint(equalToConstant: 60).isActive = true
        self.iconContainerView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor).isActive = true

        // Deactivate non-reusable constraints
        _ = self.layoutConstraints.map  $0.isActive = false 
        self.layoutConstraints = [NSLayoutConstraint]()

        if let iconView = self.iconView 
            self.imageView.isHidden = true
            self.layoutConstraints.append(iconView.centerYAnchor.constraint(equalTo: self.iconContainerView.centerYAnchor))
            self.layoutConstraints.append(iconView.centerXAnchor.constraint(equalTo: self.iconContainerView.centerXAnchor))
            self.layoutConstraints.append(iconView.heightAnchor.constraint(equalToConstant: 40))
            self.layoutConstraints.append(iconView.widthAnchor.constraint(equalToConstant: 40))
         else 
            self.imageView.isHidden = false
            self.iconView?.isHidden = true
            self.layoutConstraints.append(self.imageView.leadingAnchor.constraint(equalTo: self.iconContainerView.leadingAnchor))
            self.layoutConstraints.append(self.imageView.trailingAnchor.constraint(equalTo: self.iconContainerView.trailingAnchor))
            self.layoutConstraints.append(self.imageView.topAnchor.constraint(equalTo: self.iconContainerView.topAnchor))
            self.layoutConstraints.append(self.imageView.bottomAnchor.constraint(equalTo: self.iconContainerView.bottomAnchor))
        
        _ = self.layoutConstraints.map $0.isActive = true
    

【问题讨论】:

你不能使用两个不同的UICollectionViewCells有什么原因吗? 我使用的 collectionView 单元格相当长,图像/图标是唯一的布局差异。我不知道两个 UICollectionView 是否会提高性能,因为可以重用的单元格更少。此外,它需要在每个类和一个公共父类中重复所有约束。不是很有吸引力,但如果这是我会考虑的唯一方式。但是真的不能在单个单元格中显示自定义视图吗? 【参考方案1】:

设置时不要广告和删除 IconView。将两者添加到同一位置并更改 isHidden、alpha 或不透明度或bringSubviewToFront。这对主线程的密集程度要低得多。

【讨论】:

是的,但是每次渲染单元格时都应该显示一个全新的“IconView”。如果仅更新了 IconView 的属性,您的建议将是正确的(就像我已经为 UIImageView 所做的那样,在提供 IconView 时将被设置为隐藏)。理想情况下,IconView 也应该作为属性提供......有什么想法吗?

以上是关于如何实现可以显示图像或作为输入属性提供的自定义 UIView 的 CollectionViewCell?的主要内容,如果未能解决你的问题,请参考以下文章

显示 WooCommerce 产品属性的自定义分类术语图像

如何加载保存到我的标记 ID 的图像并显示在该特定标记的自定义信息窗口中?

Spring Boot - 如何通过实现 BeforeAllCallback 的自定义扩展类设置或覆盖 application.yml 中定义的属性?

watchkit 中的自定义元素

带有 UIImageView 的自定义 UITableViewCell 不显示图像

WIX安装程序无法正确显示WixUI对话框的自定义图像