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

使用UICollectionViewCompositionalLayout.list时如何为contentView添加内边距

为UICollectionView列表样式添加水平内边距且保留默认编辑状态

问题背景

想要为UICollectionView的contentView添加水平内边距,但设置collectionView.contentInset = UIEdgeInsets(top: .zero, left: 64, bottom: .zero, right: 64)时,内容会可横向滚动而非单元格宽度自动缩小。当前使用UICollectionViewCompositionalLayout.list创建默认列表样式,自定义NSCollectionLayoutSection时可给group加内边距,但希望保留Apple默认列表的编辑、重排等交互状态。

解决方案:通过sectionProvider自定义列表section内边距

使用UICollectionLayoutListConfiguration的sectionProvider回调,获取系统默认生成的section布局,修改其group的水平内边距即可。这种方式既能保留默认列表的所有交互逻辑,又能实现内容宽度缩小的效果,不会触发横向滚动。

关键修改步骤

  • 移除collectionView.contentInset的设置,避免内容可横向滚动
  • 在创建UICollectionLayoutListConfiguration时,设置sectionProvider回调,调整section的group内边距

修改后的完整代码

import SwiftUI
import UIKit

final class AppearancePlainViewController: UIViewController {

    struct Contact: Identifiable, Hashable {
        let id: UUID = UUID()
        let name: String = "Arthur"
        let surname: String = "Dent"
        let image: UIImage = UIImage(systemName: "person")!
    }
    
    private enum ListSection: Int {
        case main
    }
    
    private enum ListRow: Hashable {
        enum ListContentConfiguration: Hashable {
            case cell
        }
        
        case example(ListContentConfiguration, Contact)
        case description(String)
    }
    
    private typealias Section = ListSection
    private typealias Row = ListRow
    private typealias DataSource = UICollectionViewDiffableDataSource<Section, Row>
    private typealias Snapshot = NSDiffableDataSourceSnapshot<Section, Row>
    
    private let rows: [ListRow] = [
        .example(.cell, Contact()),
        .description(".cell"),
        .example(.cell, Contact()),
        .description(".cell1"),
        .example(.cell, Contact()),
        .description(".cell2"),
        .example(.cell, Contact()),
        .description(".cell3"),
        .example(.cell, Contact()),
        .description(".cell4"),
        .example(.cell, Contact()),
        .description(".cell5"),
        .example(.cell, Contact()),
        .description(".cell6"),
        .example(.cell, Contact()),
        .description(".cell7"),
        .example(.cell, Contact()),
        .description(".cell8"),
    ]
    
    private weak var collectionView: UICollectionView!
    private var datasource: DataSource!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Appearance.plain"
        view.backgroundColor = .orange
        configureViewHierarchy()
        configureDataSource()
        loadData()
        
        collectionView.isEditing = true
    }

    private func configureViewHierarchy() {
        let layout = createLayout()
        
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.delegate = self
        // 移除contentInset设置,避免横向滚动
        view.addSubview(collectionView)
        self.collectionView = collectionView
        
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        ])
    }
    
    private func createLayout() -> UICollectionViewLayout {
        var configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        // 设置sectionProvider自定义section内边距
        configuration.sectionProvider = { sectionIndex, layoutEnvironment in
            // 获取系统默认的列表section
            var section = UICollectionLayoutListConfiguration.listSection(
                for: sectionIndex,
                layoutEnvironment: layoutEnvironment,
                configuration: configuration
            )
            // 给section的group添加水平内边距
            section.contentInsets = UIEdgeInsets(top: .zero, left: 64, bottom: .zero, right: 64)
            return section
        }
        let layout = UICollectionViewCompositionalLayout.list(using: configuration)
        return layout
    }
    
    private func configureDataSource() {
        let descriptionRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, _, item in
            cell.contentConfiguration = UIHostingConfiguration {
                ZStack {
                    Text(item)
                        .font(.caption2)
                        .padding(.horizontal, 2.0)
                }
                .foregroundColor(Color(UIColor.systemBackground))
                .background(Color(UIColor.label))
                .cornerRadius(2.0)
                .padding(.bottom, 2.0)
            }
            var backgroundConfig = UIBackgroundConfiguration.listPlainCell()
            backgroundConfig.backgroundColor = .blue
            cell.backgroundConfiguration = backgroundConfig
        }
        
        let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Contact> { cell, _, item in
            var configuration = UIListContentConfiguration.cell()
            configuration.text = item.name
            configuration.secondaryText = item.surname
            configuration.image = item.image
            cell.contentConfiguration = configuration
            cell.backgroundConfiguration = .listPlainCell()
        }
        
        datasource = DataSource(collectionView: collectionView) { collectionView, indexPath, identifier -> UICollectionViewCell in
            
            switch identifier {
            case .example(let configType, let contact):
                switch configType {
                case .cell:
                    return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: contact)
                }
            case .description(let string):
                return collectionView.dequeueConfiguredReusableCell(using: descriptionRegistration, for: indexPath, item: string)
            }
        }
    }
    
    private func loadData() {
        var snapshot = Snapshot()
        snapshot.appendSections([.main])
        snapshot.appendItems(rows, toSection: .main)
        datasource.applySnapshotUsingReloadData(snapshot)
    }
}

extension AppearancePlainViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, canEditItemAt indexPath: IndexPath) -> Bool {
        return true
    }
    
    func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt currentIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
        return proposedIndexPath
    }
}

效果说明

  • 单元格内容会自动适配内边距,宽度缩小,不会出现横向滚动
  • 列表的编辑、重排等默认交互状态完全保留,没有任何破坏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:45:56