You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在UICollectionViewListCell中让自定义附属UIImageView垂直居中?

问题描述

运行以下UIKit应用,该应用使用带组合布局(列表布局)和差异数据源的集合视图,包含一个分区和一行单元格。单元格的前置附属视图是一个UIImageView:
未设置图片时,UIImageView垂直居中显示

但一旦给UIImageView设置图片,附属视图就不再垂直居中:
设置图片后,UIImageView垂直居中失效

对应的代码如下:

import UIKit

class ViewController: UIViewController {
    var collectionView: UICollectionView!
    
    var dataSource: UICollectionViewDiffableDataSource<String, String>!

    override func viewDidLoad() {
        super.viewDidLoad()

        configureHierarchy()
        configureDataSource()
    }

    func configureHierarchy() {
        collectionView = .init(frame: .zero, collectionViewLayout: createLayout())
        view.addSubview(collectionView)
        collectionView.frame = view.bounds
    }
    
    func createLayout() -> UICollectionViewLayout {
        UICollectionViewCompositionalLayout { section, layoutEnvironment in
            let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
            return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
        }
    }
    
    func configureDataSource() {
        let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
            let iv = UIImageView()
            iv.backgroundColor = .systemRed
//            iv.image = .init(systemName: "camera")
            iv.contentMode = .scaleAspectFit
            iv.frame.size = .init(
                width: 40,
                height: 40
            )
            
            cell.accessories = [.customView(configuration: .init(
                customView: iv,
                placement: .leading(),
                reservedLayoutWidth: .actual,
                maintainsFixedSize: true
            ))]
        }
        
        dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
            collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
        }
        
        var snapshot = NSDiffableDataSourceSnapshot<String, String>()
        snapshot.appendSections(["main"])
        snapshot.appendItems(["demo"])
        dataSource.apply(snapshot, animatingDifferences: false)
    }
}

这看起来像是个bug,但把UIImageView尺寸设为100x100时,即使不设置图片,单元格也不会调整大小,这让我怀疑是自己操作有误。


解决方法

问题出在直接给UIImageView设置frame,UICollectionViewListCell的附属视图布局依赖布局系统识别的视图尺寸,而非手动设置的frame。可以通过以下两种方式修复:

方式一:指定视图固有内容尺寸

替换手动设置frame的代码,直接指定UIImageView的固有内容尺寸:

let iv = UIImageView()
iv.backgroundColor = .systemRed
iv.image = UIImage(systemName: "camera")
iv.contentMode = .scaleAspectFit
// 替换frame设置为固有尺寸
iv.intrinsicContentSize = CGSize(width: 40, height: 40)

方式二:添加Auto Layout约束

给UIImageView添加固定宽高约束,让布局系统正确识别其尺寸:

let iv = UIImageView()
iv.backgroundColor = .systemRed
iv.image = UIImage(systemName: "camera")
iv.contentMode = .scaleAspectFit
iv.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    iv.widthAnchor.constraint(equalToConstant: 40),
    iv.heightAnchor.constraint(equalToConstant: 40)
])

无需修改附属视图的配置参数,保持reservedLayoutWidth: .actual和maintainsFixedSize: true即可。调整后,无论是否设置图片,UIImageView都会在附属视图区域内垂直居中,单元格也会根据内容自动适配高度。


内容的提问来源于stack exchange,提问作者Filippo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:22:29