UITableViewHeaderFooterView子视图布局问题:图片未遵循安全区域
解决UITableView自定义头部视图图片不遵循安全区域的问题
问题场景
自定义ProfileHeaderView作为UITableView第0组的头部视图后,运行发现图片未遵循屏幕安全区域,相关实现代码如下:
ProfileHeaderView 核心代码
class ProfileHeaderView: UITableViewHeaderFooterView { // MARK: - Subviews private var statusText: String = "" private lazy var userImage: UIImageView = { let imageView = UIImageView(image: UIImage(named: me.login)) imageView.layer.cornerRadius = 48 imageView.clipsToBounds = true imageView.translatesAutoresizingMaskIntoConstraints = false return imageView }() ... // MARK: - Lifecycle override init(reuseIdentifier: String?) { super.init(reuseIdentifier: reuseIdentifier) setupUI() addSuviews() setupConstraints() } // MARK: - Private private func setupUI() { backgroundColor = .lightGray } private func addSuviews() { addSubview(userImage) } private func setupConstraints() { let layoutMarginGuide = contentView.layoutMarginsGuide NSLayoutConstraint.activate([ userImage.leadingAnchor.constraint(equalTo: layoutMarginGuide.leadingAnchor, constant: 10), userImage.topAnchor.constraint(equalTo: layoutMarginGuide.topAnchor, constant: 16), userImage.bottomAnchor.constraint(equalTo: layoutMarginGuide.bottomAnchor, constant: -16), userImage.widthAnchor.constraint(equalToConstant: 90), userImage.heightAnchor.constraint(equalToConstant: 90), ]) } }
ViewController 注册代码
private func setupConstraints() { feedView.frame = view.bounds feedView.delegate = self feedView.dataSource = self feedView.register(PostViewCell.self, forCellReuseIdentifier: "cell") feedView.register(ProfileHeaderView.self, forHeaderFooterViewReuseIdentifier: "ProfileHeaderView") //feedView.register(ProfileHeaderView.self, forHeaderFooterViewReuseIdentifier: "profileView") }
修复方案
问题根源有两点:一是子视图添加到了头部视图本身而非contentView,二是使用的layoutMarginsGuide未和安全区域对齐。
1. 将子视图添加到contentView
修改addSuviews方法,把userImage添加到头部视图的contentView(这是UITableViewHeaderFooterView官方推荐的子视图容器):
private func addSuviews() { contentView.addSubview(userImage) }
2. 改用safeAreaLayoutGuide约束
直接使用contentView的safeAreaLayoutGuide来设置约束,确保视图自动适配设备的安全区域:
private func setupConstraints() { let safeGuide = contentView.safeAreaLayoutGuide NSLayoutConstraint.activate([ userImage.leadingAnchor.constraint(equalTo: safeGuide.leadingAnchor, constant: 10), userImage.topAnchor.constraint(equalTo: safeGuide.topAnchor, constant: 16), userImage.bottomAnchor.constraint(equalTo: safeGuide.bottomAnchor, constant: -16), userImage.widthAnchor.constraint(equalToConstant: 90), userImage.heightAnchor.constraint(equalToConstant: 90), ]) }
可选优化:兼容自定义边距
如果需要保留自定义的layoutMargins同时兼容安全区域,可以在setupUI中开启contentView的边距继承:
private func setupUI() { backgroundColor = .lightGray contentView.preservesSuperviewLayoutMargins = true }
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

