You need to enable JavaScript to run this app. 小屏无刘海iOS设备能否调整UICollectionView的y轴位置做适配?
优惠活动
大模型
产品
解决方案
定价
更多

小屏无刘海iOS设备能否调整UICollectionView的y轴位置做适配?

解决方案

你完全可以针对无刘海老旧设备调整y轴位置,以下是两种可行实现方案:

方案1:维持现有frame写法,动态调整y值

你当前固定写死y=162是适配了刘海屏的顶部安全区高度,无刘海设备的顶部安全区比刘海屏少24pt,所以会出现顶部留白过多的问题。你可以通过动态获取设备顶部安全区高度来计算y值,自动适配不同设备:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    collectionView?.backgroundColor = appBackgroundColor
    // 动态获取顶部安全区高度
    let topSafeAreaHeight = view.safeAreaInsets.top
    // 118为你顶部安全区以上的所有控件总高度,可根据实际需求调整
    let collectionViewTopOffset = topSafeAreaHeight + 118
    // 动态设置frame
    collectionView?.frame = CGRect(
        x: 11, 
        y: collectionViewTopOffset, 
        width: self.view.frame.width-20, 
        height: self.view.frame.height - collectionViewTopOffset - 3
    )
}

如果需要单独判断设备是否有刘海,也可以用如下扩展:

extension UIDevice {
    static var hasNotch: Bool {
        guard #available(iOS 11.0, *) else { return false }
        return UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0 > 20
    }
}

使用时直接赋值即可:

let yOffset: CGFloat = UIDevice.hasNotch ? 162 : 138
collectionView?.frame = CGRect(x: 11, y: yOffset, width: self.view.frame.width-20, height: self.view.frame.height - yOffset - 3)

方案2:使用Auto Layout约束适配,解决布局切换异常问题

你之前添加约束后无法切换布局,大概率是两个原因导致的:

  • 你在listLayout和gridLayout的懒加载代码中重复创建UICollectionView实例、重复调用addSubview,导致约束冲突
  • 代码中混用了folderCollectionView和collectionView两个变量,逻辑混乱

你可以按如下方式修改,一次添加约束永久适配所有屏幕,同时支持正常切换布局:

  1. 先删除listLayout和gridLayout懒加载中如下两行冗余代码:
// 冗余代码,全部删除
folderCollectionView = UICollectionView(frame: .zero,collectionViewLayout: listLayout)
view.addSubview(collectionView!)
  1. 改造collectionViewSetUp方法,统一初始化并添加约束:
func collectionViewSetUp() {
    // 仅初始化一次collectionView
    collectionView = UICollectionView(frame: .zero,collectionViewLayout: gridLayout)
    collectionView?.translatesAutoresizingMaskIntoConstraints = false
    collectionView?.showsVerticalScrollIndicator = false
    collectionView?.showsHorizontalScrollIndicator = false
    collectionView?.dataSource = self
    collectionView?.delegate = self
    collectionView?.allowsMultipleSelection = true
    collectionView?.allowsSelection = true
    collectionView?.isUserInteractionEnabled = true
    collectionView?.register(collectionViewListLayoutCell.self, forCellWithReuseIdentifier: "collectionViewListLayoutCell")
    collectionView?.register(collectionViewCell.self, forCellWithReuseIdentifier: "collectionViewCell")
    view.addSubview(collectionView!)
    
    // 仅添加一次约束,自动适配所有设备
    NSLayoutConstraint.activate([
        collectionView!.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 11),
        collectionView!.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -9),
        // 直接对接安全区顶部,自动适配刘海/非刘海屏
        collectionView!.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 118),
        collectionView!.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -3)
    ])
}
  1. 布局切换按钮点击事件用系统原生方法切换,不需要修改约束:
@objc func switchLayoutButtonTapped() {
    let targetLayout = isListView ? gridLayout : listLayout
    collectionView?.setCollectionViewLayout(targetLayout, animated: true)
    isListView.toggle()
}
  1. 清空viewDidLayoutSubviews中的冗余配置,仅保留必要代码:
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    collectionView?.backgroundColor = appBackgroundColor
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 23:36:04