试图确定子类 UICollectionViewCell 中的单元格宽度

Posted

技术标签:

【中文标题】试图确定子类 UICollectionViewCell 中的单元格宽度【英文标题】:Trying to determine cell width in a subclassed UICollectionViewCell 【发布时间】:2017-04-11 00:05:15 【问题描述】:

我有一个基本的子类 UICollectionView Cell。我想给它添加一个 UIImageView ,所以每个单元格都显示一个图像。

如果我向 x:y:width:height 添加显式值,图像会正确显示,但我不能使用self.contentView.frame.width 来确定集合视图单元格的大小(用于将图像放置在 x 轴上)

class SubclassedCell: UICollectionViewCell 
    var myImageView: UIImageView!
    required init?(coder aDecoder: NSCoder) 
        super.init(coder:aDecoder)
        myImageView = UIImageView(frame: CGRect(x: (self.frame.width - 10.0), y: 50.0, width: 20.0, height: 20.0))
        myImageView.image = UIImage(named: "JustinBieber")
        self.contentView.addSubview(myImageView)
    

在上面,(self.contentView.frame.width - 10.0) 没有获取集合视图单元格的大小,因此根本不显示图像。如果我明确地为 x 输入一个值,比如 0,它就会显示出来。

如何确定子类集合视图单元格的大小(宽度)?

【问题讨论】:

您能否提供有关您要完成的工作的更多详细信息?例如。您是否尝试将图像定位在距单元格右侧 10 个点的位置? 正确。我正在尝试将图像定位在距离单元格右侧 10 个点的位置。这就是为什么我需要动态确定单元格的宽度(它们的大小不一样)。 【参考方案1】:

在视图生命周期的早期调用初始化程序以准确地提供维度值。

更惯用的方法是在 layoutSubviews 生命周期方法中布局您的图像。下面是一个简单的例子

class SubclassedCell: UICollectionViewCell 

    var myImageView: UIImageView!
    var imageDisplayed = false

    override func layoutSubviews() 
        super.layoutSubviews()
        if !imageDisplayed 
            myImageView = UIImageView(frame: CGRect(x: (self.frame.width - 10.0), y: 50.0, width: 20.0, height: 20.0))
            myImageView.image = UIImage(named: "JustinBieber")
            self.contentView.addSubview(myImageView)
            imageDisplayed = true
        
    

如果您在应用程序中使用自动布局,您可能还需要考虑添加图像并提供约束,而不是显式设置图像的框架。

如answer 中所示 - 取决于您的用例 - 它们可能是设置单元的更好方法。

【讨论】:

请注意,layoutSubviews 在视图的生命周期内可以多次调用 感谢您的帮助,但就像@sooper 提到的那样,layoutSubviews 会被调用多次,因此这会导致单元格基本上到处喷出 imageViews。 @joe - 我已经修改了这个例子,只在初次调用layoutSubviews 时将图像添加到视图中 - 有很多方法可以完成你想要做的事情 - 主要的事情要考虑的是视图的哪些属性在其生命周期的哪个阶段有用 p.s - 属性名称中的拼写错误:var imageDispalyed = false(我尝试编辑它,但编辑需要 6 个字符) 你试过把逻辑放在awakeFromNib吗?【参考方案2】:

有很多方法可以实现这种布局,您不需要知道宽度的约束。您定义所需的关系,其余的由布局系统管理。

class SubclassedCell1: UICollectionViewCell 
    var myImageView: UIImageView!

    private func commonInit() 
        myImageView = UIImageView()
        myImageView.image = UIImage(named: "JustinBieber")
        myImageView.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.addSubview(myImageView)

        NSLayoutConstraint.activate([
            myImageView.widthAnchor.constraint(equalToConstant: 20),
            myImageView.heightAnchor.constraint(equalToConstant: 20),
            myImageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 50),
            myImageView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 10),
            ])
    

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

    required init?(coder aDecoder: NSCoder) 
        super.init(coder:aDecoder)
        commonInit()
    

你也可以使用 layoutSubviews,就像@syllabix 提到的那样。执行此操作时,请确保在每次调用 layoutSubviews 时更新框架,否则如果调整大小,您的视图将无法正确更新。在布置子视图时,还要使用父视图边界,而不是框架。

class SubclassedCell2: UICollectionViewCell 
    var myImageView: UIImageView!

    private func commonInit() 
        myImageView = UIImageView()
        myImageView.image = UIImage(named: "JustinBieber")
        self.contentView.addSubview(myImageView)
    

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

    required init?(coder aDecoder: NSCoder) 
        super.init(coder:aDecoder)
        commonInit()
    

    override func layoutSubviews() 
        super.layoutSubviews()
        myImageView.frame = CGRect(x: (self.bounds.maxX - 10.0), y: 50.0, width: 20.0, height: 20.0)
    

【讨论】:

以上是关于试图确定子类 UICollectionViewCell 中的单元格宽度的主要内容,如果未能解决你的问题,请参考以下文章

确定子类是不是具有在 Python 中实现的基类方法

确定 UITabBar 项属于哪个 UIViewController 子类

Symfony2 从超类确定和访问子类

多态的概念和用法

Widevine 视频播放

模板方法设计模式