수평으로 UICollectionView 셀을 중앙에 배치하는 방법은 무엇입니까?


123

몇 가지 연구를 수행했지만 UICollectionView에서 셀을 가로로 가운데에 배치하는 방법에 대한 코드 예제를 찾을 수 없습니다.

첫 번째 셀이 X00 과 같은 대신 과 같은 것이 아니라이 0X0같기를 원합니다 . 이것을 달성하는 방법이 있습니까?

편집하다:

내가 원하는 것을 시각화하려면 :

여기에 이미지 설명 입력

CollectionView에 요소가 하나만있을 때 버전 B처럼 보이도록해야합니다. 요소가 두 개 이상 있으면 버전 A와 비슷하지만 요소가 더 많아야합니다.

지금은 요소가 1 개 뿐인데 버전 A처럼 보이며 어떻게 B처럼 보이게 만들 수 있는지 궁금합니다.

도와 주셔서 감사합니다!


셀을 컬렉션 뷰의 너비에 맞추고 컬렉션 뷰 자체를 부모 내 중앙에 배치하는 것이 더 쉽지 않습니까?
Arthur Gevorkyan 2015

예,이를 수행하는 최소한 두 가지 방법이 있습니다. 첫 번째 (빠른)는 전체 화면의 셀 너비를 만들고 하위 뷰를 중앙에 배치하는 것입니다. 두 번째 (오른쪽) 사용자 지정 컬렉션보기 레이아웃 구현
sage444

백엔드에서 오는 결국 이상의 셀, 좋은 생각되지 않을 것입니다 전체 폭을 채우고있을 것입니다
RaptoX

폭이 중심에 세트에 충분 증가
키 쇼어 쿠마르

답변:


227

라이브러리를 사용하는 것은 좋은 생각이 아닙니다. 만약 당신의 목적이 이것이 바로 중앙 정렬이라면.

collectionViewLayout 함수에서이 간단한 계산을 더 잘 수행 할 수 있습니다.

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    let totalCellWidth = CellWidth * CellCount
    let totalSpacingWidth = CellSpacing * (CellCount - 1)

    let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

2
@DarshanPatel. 내가 이것을 구현 한 많은 답변에 감사 드리며 행이 중앙에 올랐지 만 이제 문제는 첫 번째 항목으로 스크롤 할 수 없다는 것입니다. 첫 번째 항목으로 스크롤하려고하면 수정 된 UIEdgeInsets로 돌아갑니다. 당신은 내 데모 애플리케이션 볼 수 있습니다 github.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
Swift 3에서 새로운 메서드 서명은 collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Kamchatka

1
cellWidth를 어떻게 잡을 수 있습니까? cellForItemAt 메소드를 통해 가능합니까? 나는 시도했고 그것은 nil .. 화면 크기에 따라 변경된 셀 너비를 반환했습니다 .. @DarshanPatel.
Chris

10
@DarshanPatel. 귀하의 답변은 때때로 더 작은 장치에서 음의 값을 생성 할 수 있습니다. 다음 leftInset과 같이 귀하의 가치 에 대해 최대 검사를 사용하는 것이 let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
좋습니다

3
UICollectionViewController를 서브 클래 싱하지 않는 경우 클래스가 UICollectionViewDelegateFlowLayout을 준수하는지 확인하십시오. 그렇지 않으면 작동하지 않습니다.
Saeed Ir

59

스위프트 5.1

func centerItemsInCollectionView(cellWidth: Double, numberOfItems: Double, spaceBetweenCell: Double, collectionView: UICollectionView) -> UIEdgeInsets {
    let totalWidth = cellWidth * numberOfItems
    let totalSpacingWidth = spaceBetweenCell * (numberOfItems - 1)
    let leftInset = (collectionView.frame.width - CGFloat(totalWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset
    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

스위프트 4.2

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
    let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

    let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)

}

스위프트 3

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

        let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
        let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

        let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
        let rightInset = leftInset

        return UIEdgeInsetsMake(0, leftInset, 0, rightInset)

    }

프로토콜을 추가하는 것을 잊지 마세요

UICollectionViewDelegateFlowLayout

어쩌면 @ashForIos을 제약 조건
아흐메드 Safadi

셀 수가 증가하면 셀이 중앙에 있고 첫 번째 셀이나 마지막으로 스크롤 할 수 없을 때 collectionView에 맞는 셀이있을 때 답변이 제대로 작동합니다.
NickCoder 19 dec

2
@Vitalii 80은 셀 너비를 의미하고 10은 셀 사이의 공백을 의미합니다. 변수 이름을 읽으면 의미를 이해할 수 있습니다. P
Ahmed Safadi

Swift 4.2 솔루션은 더 쉽습니다. 감사합니다! 실제 셀 개체 너비가 무엇이든 "80"을 설정해야합니다.
John Pitts

25

Swift 4에 사용해보세요

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = 165.0

        let numberOfCells = floor(self.view.frame.size.width / cellWidth)
        let edgeInsets = (self.view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(15, edgeInsets, 0, edgeInsets)
    }

165.0 대신 cellWidth 추가


1
이것이 최고의 대답입니다. 그것에 가장 간단한 수학. 행과 열의 수에 제한이 없습니다
rickrvo

20

이를 위해 KTCenterFlowLayout 을 사용 하며 훌륭하게 작동합니다. UICollectionViewFlowLayout원하는대로 중앙 셀 의 사용자 지정 하위 클래스입니다 . (참고 : 이것은 일부 코드를 게시하여 해결하는 사소한 일이 아니기 때문에 GitHub 프로젝트에 연결합니다!)


IB에서 작동하지 못했습니다. 이 도서관 은 저에게 매력적으로 작용했습니다. 포드를 설치하고 IB의 레이아웃 클래스를 변경했습니다!
tagirkaZ

15

Darshan Patel의 답변에 대한 객관적인 C 버전 :

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    CGFloat totalCellWidth = kItemWidth * self.dataArray.count;
    CGFloat totalSpacingWidth = kSpacing * (((float)self.dataArray.count - 1) < 0 ? 0 :self.dataArray.count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

감사. 단일 행으로 잘 작동합니다. 그러나 여러 행에 문제가 발생합니다. 여기에 URL을 추가하여 스크린 샷을 표시 할 수 없습니다. . 하지만 작은 URL에 "yynoalzg"를 추가 할 수 있습니다. 당신은 아이디어를 얻을 것입니다. 골드 섹션에는 4 개의 기록이 있습니다. 4 번째 줄은 새 줄에 있어야합니다. .하지만이 방법을 사용하면 다음과 같이 표시됩니다. 아이디어가 있으면 알려주세요.
Hitarth 2019

6

@Safad Funy의 답변을 약간 수정하면 Swift 및 iOS의 최신 버전에서 저에게 효과적이었습니다. 이 경우 셀 너비가 컬렉션 뷰 크기의 1/3이되기를 원했습니다.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

  let totalCellWidth = Int(collectionView.layer.frame.size.width) / 3 * collectionView.numberOfItems(inSection: 0)
  let totalSpacingWidth = (collectionView.numberOfItems(inSection: 0) - 1)

  let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
  let rightInset = leftInset

  return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

2
이것은 특히 셀이 하나뿐 일 때 저에게 효과적이었습니다.
Dasoga

6

이 확장 프로그램 (Swift 4)을 사용할 수 있습니다.

당신 collectionView이 가지고 있다면 그것은 세포를 중심에 둘 수 있습니다layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize .

모든 세포 크기에서 작동하며 다음과 같은 경우 완벽하게 작동합니다. scrollDirection = .horizontal

public extension UICollectionView {
    func centerContentHorizontalyByInsetIfNeeded(minimumInset: UIEdgeInsets) {
        guard let layout = collectionViewLayout as? UICollectionViewFlowLayout,
            layout.scrollDirection == .horizontal else {
                assertionFailure("\(#function): layout.scrollDirection != .horizontal")
                return
        }

        if layout.collectionViewContentSize.width > frame.size.width {
            contentInset = minimumInset
        } else {
            contentInset = UIEdgeInsets(top: minimumInset.top,
                                        left: (frame.size.width - layout.collectionViewContentSize.width) / 2,
                                        bottom: minimumInset.bottom,
                                        right: 0)
        }
    }
}


final class Foo: UIViewController {
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView.centerContentHorizontalyByInsetIfNeeded(minimumInset: yourDefaultInset)
    }
}

도움이되기를 바랍니다!


1
오류 발생 : 스레드 1 : EXC_BAD_ACCESS (코드 = 2, 주소 = 0x118ffde58)
atulkhatri

4

Swift 4.2 (수평 및 수직). Pink Panther 코드의 작은 업그레이드이며 그에게 큰 감사를드립니다!


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellHieght: CGFloat = flowLayout.itemSize.height
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var collectionHeight = collectionView.frame.size.height
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
        collectionHeight -= collectionView.safeAreaInsets.top + collectionView.safeAreaInsets.bottom
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    let totalHieght = cellHieght * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInsetWidth = (collectionWidth - totalWidth) / 2

        print(edgeInsetWidth, edgeInsetWidth)
        return UIEdgeInsets(top: 5, left: edgeInsetWidth, bottom: flowLayout.sectionInset.top, right: edgeInsetWidth)
    } else {
        let edgeInsetHieght = (collectionHeight - totalHieght) / 2
        print(edgeInsetHieght, edgeInsetHieght)
        return UIEdgeInsets(top: edgeInsetHieght, left: flowLayout.sectionInset.top, bottom: edgeInsetHieght, right: flowLayout.sectionInset.top)

    }
}

클래스가 UICollectionViewDelegateFlowLayout 프로토콜을 준수하는지 확인하십시오.


정말 당신의 코드는 저에게 잘 작동합니다. 고마워요 Dude; )
steveSarsawa

4

다음은 셀이 둘 이상의 행일 때도 잘 작동하는 Swift 5 의 최신 버전입니다 .

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    var cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var totalWidth: CGFloat
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    repeat {
        totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
        cellCount -= 1
    } while totalWidth >= collectionWidth

    if (totalWidth > 0) {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsets.init(top: flowLayout.sectionInset.top, left: edgeInset, bottom: flowLayout.sectionInset.bottom, right: edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

클래스 가 프로토콜을 준수 하는지 확인하십시오 UICollectionViewDelegateFlowLayout.


3

스위프트 4

extension ViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

        let cellWidth: CGFloat = 170.0 // Your cell width

        let numberOfCells = floor(view.frame.size.width / cellWidth)
        let edgeInsets = (view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets)
    }

 }

2

패딩 만 추가하려는 사용자 ( top, left, bottom, right ) :

프로토콜 추가 UICollectionViewDelegateFlowLayout

이 예제는 왼쪽과 오른쪽에 40으로 패딩을 표시합니다.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {        
    return UIEdgeInsetsMake(0, 40, 0, 40)
}

2

SWIFT 4.2

private lazy var contentView: UICollectionView = {
        let layoutView: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layoutView.scrollDirection = .horizontal
            layoutView.minimumInteritemSpacing = 0
            layoutView.minimumLineSpacing = 5

        let collectionView: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: layoutView)
            collectionView.dataSource = self
            collectionView.delegate = self
            collectionView.showsHorizontalScrollIndicator = false
            collectionView.isPagingEnabled = true
            collectionView.registerCell(Cell.self)
            collectionView.backgroundColor = .clear
            collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

//

extension CustomCollectionView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: collectionView.frame.width*4/5, height: collectionView.frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = collectionView.frame.width*4/5

        let numberOfCells = floor(collectionView.frame.width / cellWidth)
        let edgeInsets = (collectionView.frame.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsets(top: 0, left: edgeInsets, bottom: 0, right: edgeInsets)
    }
}

1

내 솔루션을 시도해 볼 수 있습니다.

func refreshCollectionView(_ count: Int) {
    let collectionViewHeight = collectionView.bounds.height
    let collectionViewWidth = collectionView.bounds.width
    let numberOfItemsThatCanInCollectionView = Int(collectionViewWidth / collectionViewHeight)
    if numberOfItemsThatCanInCollectionView > count {
        let totalCellWidth = collectionViewHeight * CGFloat(count)
        let totalSpacingWidth: CGFloat = CGFloat(count) * (CGFloat(count) - 1)
        // leftInset, rightInset are the global variables which I am passing to the below function
        leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2;
        rightInset = -leftInset
    } else {
        leftInset = 0.0
        rightInset = -collectionViewHeight
    }
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

1

허용 대답은 정답입니다하지만이 경우 totalCellWidth미만 CollectionViewwidth이에 대해,하지만 단지 경비에 당신은 다음과 같이 할 수 있습니다.

if (leftInset > 0) {
     return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
  } else {
     return UIEdgeInsetsMake(0, 10, 0, 10)
}

1

이 코드는 수정없이 Swift 4.0 에서도 수평 컬렉션 뷰를 중앙에 배치해야합니다 .

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsetsMake(flowLayout.sectionInset.top, edgeInset, flowLayout.sectionInset.bottom, edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

클래스가 UICollectionViewDelegateFlowLayout프로토콜을 준수하는지 확인하십시오.


0

나는 여기서 완전히 다른 접근 방식을 취하게되었고, 언급 할 가치가 있다고 생각합니다.

컬렉션 뷰에 대한 제약 조건을 중앙에 수평으로 정렬하도록 설정했습니다. 그런 다음 너비를 지정하는 다른 제약 조건을 설정합니다. 컬렉션 뷰를 보유하는 viewController 내부에 너비 제약에 대한 콘센트 만들었습니다 . 그런 다음 데이터 소스가 변경되고 컬렉션 뷰를 업데이트 할 때 셀 수를 가져 와서 (매우 유사한) 계산을 수행하여 너비를 재설정합니다.

let newWidth = (items.count * cellWidth) + (items.count * cellSpacing)

그런 다음 제약 콘센트의 .constant값을 계산 결과로 설정하고 자동 레이아웃이 나머지 작업을 수행합니다.

이것은`UICollectionViewDelegateFlowLayout과 충돌 할 수 있지만 이것은 왼쪽 정렬 된 컬렉션 뷰를 만드는 데 완벽하게 작동했습니다. 대리자가 없으면 셀이 뷰의 대부분을 채울 때만 작동하는 것처럼 보입니다.


0

페이지가 너비보다 작 으면 페이지를 중앙에 배치하고 페이지가 더 많으면 왼쪽으로 정렬하는 플로우 레이아웃에 대한 일반적인 솔루션

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    // Centering if there are fever pages
    CGSize itemSize = [(UICollectionViewFlowLayout *)collectionViewLayout itemSize];
    CGFloat spacing = [(UICollectionViewFlowLayout *)collectionViewLayout minimumLineSpacing];

    NSInteger count = [self collectionView:self numberOfItemsInSection:section];
    CGFloat totalCellWidth = itemSize.width * count;
    CGFloat totalSpacingWidth = spacing * ((count - 1) < 0 ? 0 : count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    if (leftInset < 0) {
        UIEdgeInsets inset = [(UICollectionViewFlowLayout *)collectionViewLayout sectionInset];
        return inset;
    }
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

Swift 버전 (ObjC에서 변환)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // Centering if there are fever pages
    let itemSize: CGSize? = (collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize
    let spacing: CGFloat? = (collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing

    let count: Int = self.collectionView(self, numberOfItemsInSection: section)
    let totalCellWidth = (itemSize?.width ?? 0.0) * CGFloat(count)
    let totalSpacingWidth = (spacing ?? 0.0) * CGFloat(((count - 1) < 0 ? 0 : count - 1))
    let leftInset: CGFloat = (bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2
    if leftInset < 0 {
        let inset: UIEdgeInsets? = (collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset
        return inset!
    }
    let rightInset: CGFloat = leftInset
    let sectionInset = UIEdgeInsets(top: 0, left: Float(leftInset), bottom: 0, right: Float(rightInset))
    return sectionInset
}

Untitled-3.png


신속한 코드의 경계는 무엇입니까? 해결되지 않은 식별자 '경계'오류 사용
Sachin Tanpure

안녕, 내 예제에서 나는 경계, 다른 곳에서 그것을 구현하는 경우, 적절한 경계를 사용할 수있는 UIView의 내부 메소드 구현
피터 Lapisu


0

가장 간단한 방법은 스토리 보드 또는 코드를 사용하여 컬렉션 뷰 추정 크기를 없음으로 설정하는 것입니다. layout.estimatedItemSize = CGSize.zero


0

그룹당 하나의 셀만있는 경우 a leading:trailing:of .flexible(0)는 셀을 가로로 가운데에 배치합니다.

item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
    leading: .flexible(0), top: nil,                                                     
    trailing: .flexible(0), bottom: nil
)

0

프로젝트에서 그 코드를 사용했습니다. 이 방향 모두에서 수평 및 수직 collectionView을 중심 .horizontal.vertical부의 세트를 사용. 설정된 경우 섹션의 간격과 원래 삽입을 존중합니다. 재사용을 위해 스토리 보드에서 UICollectionViewDelegateFlowLayout검색 UIcollectionView하거나 설정 하는 데 필요한 모든 속성에 액세스 할 수 있도록 델리게이트에서 사용할 코드 입니다.

// original function of the delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // casting the layout as a UICollectionViewFlowLayout to have access to the properties of items for reusability - you could also link the real one from the storyboard with an outlet
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    // getting all the properties we need
    let itemWidth = flowLayout.itemSize.width
    let itemHeight = flowLayout.itemSize.height
    let interSpacing = flowLayout.minimumInteritemSpacing
    let lineSpacing = flowLayout.minimumLineSpacing
    // getting the size of the collectionView
    let collectionWidth = collectionView.bounds.width
    let collectionHeight = collectionView.bounds.height
    // getting the direction to choose how to align the collection
    let direction = flowLayout.scrollDirection
    // you don't want to have an item greater than the collection
    guard (itemWidth < collectionWidth && direction == .vertical) || (itemHeight < collectionHeight && direction == .horizontal) else {
        print("Really?")
        return UIEdgeInsets(top: flowLayout.sectionInset.top, left: flowLayout.sectionInset.left, bottom: flowLayout.sectionInset.bottom, right: flowLayout.sectionInset.right)
    }
    // getting the number of item in the current section
    let totalItemCount = CGFloat(collectionView.numberOfItems(inSection: section))
    // setting number of item in a row to the max number of items that can fit in a row without spacing or to the number of items in the section if less than the max
    var itemCountInRow = totalItemCount < (collectionWidth / itemWidth).rounded(.towardZero) ? totalItemCount : (collectionWidth / itemWidth).rounded(.towardZero)
    // how many max row can we have
    var countOfRow = totalItemCount < (collectionHeight / itemHeight).rounded(.towardZero) ? totalItemCount : (collectionHeight / itemHeight).rounded(.towardZero)
    // calculating the total width of row by multiplying the number of items in the row by the width of item and adding the spacing multiplied by the number of item minus one
    var totalWidthOfRow:CGFloat {
        get{
            return (itemWidth * itemCountInRow) + (interSpacing * (itemCountInRow - 1))
        }
    }
    // calculating the total height of row by multiplying the number of row by the height of item and adding the spacing multiplied by the number of row minus one
    var totalHeightOfRow:CGFloat {
        get{
            return (itemHeight * countOfRow) + (lineSpacing * (countOfRow - 1))
        }
    }
    // first we set the inset to the default
    var edgeInsetLeft = flowLayout.sectionInset.left
    var edgeInsetTop = flowLayout.sectionInset.top

    if direction == .vertical {
        // while the width of row with original margin is greater than the width of the collection we drop one item until it fits
        while totalWidthOfRow > collectionWidth || ((collectionWidth - totalWidthOfRow) / 2) < flowLayout.sectionInset.left {
            // droping an item to fit in the row
            itemCountInRow -= 1
        }
        // calculating the number of rows in collectionView by dividing the number of items by the number of items in a row
        countOfRow = (totalItemCount / (itemCountInRow)).rounded(.up)
    } else {
        itemCountInRow = (totalItemCount / countOfRow).rounded(.up)
        // while the height of row with original marginis greater than the height of the collection we drop one row until it fits
        while totalHeightOfRow >= collectionHeight  || ((collectionHeight - totalHeightOfRow) / 2) < flowLayout.sectionInset.top  {
            // droping an item to fit in the row
            countOfRow -= 1
        }
    }
    edgeInsetLeft = max(flowLayout.sectionInset.left, (collectionWidth - totalWidthOfRow) / 2)
    edgeInsetTop = max(flowLayout.sectionInset.top, (collectionHeight - totalHeightOfRow) / 2)
    // we don't specially need insets where the items are overflowing
    let edgeInsetRight = direction == .vertical ? edgeInsetLeft : flowLayout.sectionInset.right
    let edgeInsetBottom = direction == .horizontal ? edgeInsetTop : flowLayout.sectionInset.bottom
    // returning the UIEdgeInsets
    return UIEdgeInsets(top: edgeInsetTop, left: edgeInsetLeft, bottom: edgeInsetBottom, right: edgeInsetRight)
}

누군가 도움이 될 희망 - 그렇지 않은 항목 섹션 안에 섹션을 중심으로 더 많은 우리가 하위 클래스가 위해 UICollectionViewFlowLayout또는 UICollectionViewLayout애플의 모자이크 예로서.


-3

나는 당신이 중심 셀 필요가 있다고 생각하므로 collectionView를 사용하는 대신 UITableView가 큰 도움이 될 것입니다. UIViewController를 사용하고 두 개의 UIView를 앞뒤에 배치하고 UITableView중간에 배치하십시오 .


정확히 필요한 것을 보여 드리기 위해 사진을 추가했습니다. 감사합니다!
RaptoX 2015
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.