UICollectionView의 셀 간격


197

섹션에서 셀 간격을 어떻게 설정 UICollectionView합니까? minimumInteritemSpacing5.0으로 설정 한 속성 이 있지만 간격이 5.0으로 표시되지 않는 것을 알고 있습니다 . flowout delegate 메소드를 구현했습니다.

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{

    return 5.0;
}

여전히 원하는 결과를 얻지 못했습니다. 나는 최소한의 간격을 생각합니다. 최대 간격을 설정할 수있는 방법이 없습니까?

시뮬레이터 사우스 캐롤라이나


대리자 메소드에 들어 갔는지 여부를 확인 했습니까?
— Nikam

예, IB에서 델리게이트에 들어가고 있습니다. 최소 셀 간격을 5로 설정했습니다. 그러나 최소 공간이 셀 사이의 최소 공간이 5가되도록해야하기 때문에 나를 도울 수있는 속성이라고 생각하지 않습니다. 컬렉션 뷰에 추가 공간이 있으면 해당 추가 공간을 사용합니다. 최대 셀 간격과 같은 것이 있어야합니다
— Vishal Singh

나도 같은 문제가있어. 5px가 작동하지 않는 것 같습니다. 나는 UITableView로 이것을 할 수 있지만 UICollectionView로는 이것을 할 수 없다.
— jerik

나는 그것을 계산하는 것을 고쳤다. 나는 그것을 내일에 게시 할 것이다. :)
— Vishal Singh

2016 년 참고 사항은 쉽습니다 : stackoverflow.com/a/28327193/294884
— Fattie

답변:


145

나는 그 주제가 오래되었다는 것을 알고 있지만, 여전히 당신이 필요로하는 사람이 여기에 정답을 필요로하는 경우 :

  1. 표준 흐름 레이아웃을 재정의합니다.
  2. 다음과 같은 구현을 추가하십시오.

    - (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
        NSArray *answer = [super layoutAttributesForElementsInRect:rect];
    
        for(int i = 1; i < [answer count]; ++i) {
            UICollectionViewLayoutAttributes *currentLayoutAttributes = answer[i];
            UICollectionViewLayoutAttributes *prevLayoutAttributes = answer[i - 1];
            NSInteger maximumSpacing = 4;
            NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
    
            if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
                CGRect frame = currentLayoutAttributes.frame;
                frame.origin.x = origin + maximumSpacing;
                currentLayoutAttributes.frame = frame;
            }
        }
        return answer;
    }

maximumSpacing은 원하는 값으로 설정할 수 있습니다. 이 트릭은 셀 사이의 공간이 정확히 최대 간격과 동일하다는 것을 보장합니다 !!


그래서 우리는 이것을 어디에 두겠습니까?
— Jonny

1
Jonny, 표준 흐름 레이아웃을 상속하고이 메소드를 복사하여 클래스에 붙여 넣기 만하면됩니다.
— iago849

1
mutableCopy배열 을 만들 필요 는 없습니다. 배열의 내용을 변경하지 않고 그 안에있는 객체를 변경하십시오.
— Brock Boland

5
어쩌면 내가 잘못
— 했거나이

2
좋은 포스트. 어떤 상황에서는 레이아웃의 마지막 줄의 서식을 뒤집는 데 오류가 발생했습니다. 해결하기 위해 ifAND를 추가 조건으로 변경했습니다 . if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x) {
— chrisoneiota

190

초기 질문을 지원합니다. 나는 간격을 5px로하려고 UICollectionView했지만 이것이 작동하지 않습니다 UIEdgeInsetsMake(0,0,0,0)...

UITableView에서 행에 x, y 좌표를 직접 지정 하여이 작업을 수행 할 수 있습니다 ...

여기에 이미지 설명을 입력하십시오

내 UICollectionView 코드는 다음과 같습니다.

#pragma mark collection view cell layout / size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [self getCellSize:indexPath];  // will be w120xh100 or w190x100
    // if the width is higher, only one image will be shown in a line
}

#pragma mark collection view cell paddings
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {

    return 5.0;
}

업데이트 : 다음 코드로 내 문제를 해결했습니다.

여기에 이미지 설명을 입력하십시오

ViewController.m

#import "ViewController.h"
#import "MagazineCell.h" // created just the default class. 

static NSString * const cellID = @"cellID";

@interface ViewController ()

@end

@implementation ViewController

#pragma mark - Collection view
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 30;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

    mCell.backgroundColor = [UIColor lightGrayColor];

    return mCell;
}

#pragma mark Collection view layout things
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"SETTING SIZE FOR ITEM AT INDEX %d", indexPath.row);
    CGSize mElementSize = CGSizeMake(104, 104);
    return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
   // return UIEdgeInsetsMake(0,8,0,8);  // top, left, bottom, right
    return UIEdgeInsetsMake(0,0,0,0);  // top, left, bottom, right
}

@end

이것은 훨씬 더 나은 대답입니다. UICollectionViewDelegateFlowLayout에서 조정할 수있는 콜백을 살펴보고 이것이 어떻게 조정되는지 확인할 수 있습니다.
— cynistersix

1
항목 + 간격의 너비가 uicollectionview의 너비와 같은 경우에만 작동합니다.
— xi.lin

@JayprakashDubey는 현재 신속하지 않습니다. 당신은 그것을 시도해야합니다. 행운을 빌어
— jerik

5px의 셀 사이의 너비를 어디에 지정합니까?
— UKDataGeek

1
UICollectionViewLayout 하위 클래스를 하나의 메서드를 재정의하는 것만으로도 오버 킬처럼 보일 수 있으며 재정의 해야하는 다른 모든 메서드를 고려할 때 사소한 문제가 아니기 때문에 허용 된 것보다 훨씬 나은 대답입니다.
— Cindeselia

80

수평 흐름 레이아웃을 사용하여 셀 사이에 10 포인트 간격을 얻었습니다. 간격을 제거하려면 0 minimumLineSpacing뿐만 아니라 설정해야했습니다 minimumInterItemSpacing.

UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.itemSize = CGSizeMake(cellWidth, cellHeight);
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 0;
flow.minimumLineSpacing = 0;

또한 모든 셀의 크기가 동일한 경우 대리자 메서드를 사용하는 대신 흐름 레이아웃에서 속성을 직접 설정하는 것이 더 간단하고 효율적입니다.


34
놀랍게도 minimumLineSpacing은 셀 사이의 수평 공간에 영향을줍니다.
— Matt H

4
나도 셀 사이에 가로 스크롤과 간격이 필요하며 minimumLineSpacing = 0이 핵심입니다.
— Wingzero

3
를 사용 하지 않고이 효과를 얻을 수있었습니다 minimumInteritemSpacing. minimumLineSpacing = 0가로 레이아웃을 설정 하면 항목 사이의 가로 간격이 제거되었습니다.
— Ziewvater

1
당신이 그것에 대해 생각하면, 항목 사이의 수평 거리는 수평으로 흐르는 레이아웃의 줄 간격입니다. 줄 간격은 일반적인 세로 방향 레이아웃에서 항목 간의 세로 거리입니다.
— lancejabr

62

그것이 기억 최소한의 줄 간격 , 최소하지 간 항목 간격 또는 셀 공간. collectionView의 스크롤 방향은 HORIZONTAL 입니다.

수직 인 경우 셀 간 가로 공간에 대해 셀 공간 또는 항목 간 공간을 설정하고 셀 간 세로 공간에 대한 줄 간격을 설정해야합니다.

Objective-C 버전

- (CGFloat)collectionView:(UICollectionView *)collectionView
                       layout:(UICollectionViewLayout*)collectionViewLayout
    minimumLineSpacingForSectionAtIndex:(NSInteger)section
    {
        return 20;
    }

스위프트 버전 :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 20
}

이제 0을 반환하면 하단 공간이 사라집니다. 오른쪽 공간을 제거하는 방법?
— Bangalore

안녕하세요, 귀하의 질문을 잘 이해하지 못했습니다. 그러나 나는 insetForSectionAtIndex 가 당신이 찾고있는 것이라고 생각 합니다. -(UIEdgeInsets) collectionView : (UICollectionView *) collectionView 레이아웃 : (UICollectionViewLayout *) collectionViewLayout insetForSectionAtIndex : (NSInteger) 섹션 {return UIEdgeInsetsMake (5, 10, 5, 10); }
— Vincent Joy

가로 및 세로 모두에 대한 최소 줄 간격입니다.
— Swati

당신은 내 하루를 구했습니다 (Y).
— Umair_UAS

어머나! 나는 이것을 믿을 수 없다. 감사합니다
— Magoo

36

이 코드를 사용하여 각 항목 사이의 간격이 5px인지 확인하십시오.

- (UIEdgeInsets)collectionView:(UICollectionView *) collectionView 
                        layout:(UICollectionViewLayout *) collectionViewLayout 
        insetForSectionAtIndex:(NSInteger) section {

    return UIEdgeInsetsMake(0, 0, 0, 5); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *) collectionView
                   layout:(UICollectionViewLayout *) collectionViewLayout
  minimumInteritemSpacingForSectionAtIndex:(NSInteger) section {    
    return 5.0;
}

SO에 잘 표시되도록 코드를 코드 블록으로 형식화하십시오.
— 도관

33

가장 인기있는 답변의 신속한 버전. 셀 사이의 간격은 같습니다 cellSpacing.

class CustomViewFlowLayout : UICollectionViewFlowLayout {

    let cellSpacing:CGFloat = 4

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        if let attributes = super.layoutAttributesForElementsInRect(rect) {
        for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
        }
        return nil
    }
}

super.layoutAttributesForElements (in : rect)가 전혀 아이디어를 반환하지 않습니까?
— Ashok R

이것을 사용하는 다른 모든 방법과 마찬가지로 이것은 여러 행에 대해 제대로 작동하지 않습니다. 적절한 대리자 메서드 및 속성이 0을 사용하도록 설정되어 있어도 간헐적으로 반올림 오류 스타일 간격이 행 사이에 유지됩니다. UICollectionView 렌더링 문제 일 수 있습니다.
— Womble

30

IB를 사용하여 셀이나 행 사이의 간격을 구성하는 매우 쉬운 방법을 찾았습니다.

스토리 보드 / Xib 파일에서 UICollectionView를 선택 하고 아래 이미지에 지정된 크기 검사기 를 클릭하십시오 .

여기에 이미지 설명을 입력하십시오

프로그래밍 방식으로 공간을 구성하려면 다음 속성을 사용하십시오.

1) 행간 간격을 설정합니다.

[self.collectionView setMinimumLineSpacing:5];

2) 항목 / 셀 사이의 공간을 설정합니다.

[self.collectionView setMinimumInteritemSpacing:5];

1
그 최소 공간은 지정된 값보다 크며 항상 지정된 값은 아닙니다.
— Vishal Singh 8

21

속성 이름 minimumInterItemSpacing을 참고하십시오 . 이것은 정확한 항목이 아닌 항목 사이 의 최소 간격입니다. 간격이 . minimumInterItemSpacing을 일부 값으로 설정하면 간격이 그보다 작은 값이되지 않도록 할 수 있습니다. 그러나 더 높은 가치를 얻을 가능성이 있습니다.

실제로 항목 사이의 간격은 여러 가지 요소 itemSize 및 sectionInset 에 따라 다릅니다 . 콜렉션보기는 이러한 값을 기반으로 컨텐츠를 동적으로 배치합니다. 따라서 정확한 간격을 보장 할 수 없습니다. sectionInset 및 minimumInterItemSpacing 과 함께 시행 착오를해야합니다 .


1
@ 모든 가장자리 곤충? : D
— NightFury

10
sectionInsects에 버그가있을 수 있습니다.
— Nestor

24
곤충 == 버그 && 곤충! = 삽입 :)
— Nestor

16

Swift 3.0, Xcode 8에 대한 답변

1. 컬렉션 뷰 델리게이트를 설정했는지 확인하십시오

class DashboardViewController: UIViewController {
    @IBOutlet weak var dashboardCollectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        dashboardCollectionView.delegate = self
    }
}

2. UICollectionViewDelegate가 아닌 UICollectionViewDelegateFlowLayout 프로토콜을 구현하십시오.

extension DashboardViewController: UICollectionViewDelegateFlowLayout {
    fileprivate var sectionInsets: UIEdgeInsets {
        return .zero
    }

    fileprivate var itemsPerRow: CGFloat {
        return 2
    }

    fileprivate var interitemSpace: CGFloat {
        return 5.0
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let sectionPadding = sectionInsets.left * (itemsPerRow + 1)
        let interitemPadding = max(0.0, itemsPerRow - 1) * interitemSpace
        let availableWidth = collectionView.bounds.width - sectionPadding - interitemPadding
        let widthPerItem = availableWidth / itemsPerRow

        return CGSize(width: widthPerItem, height: widthPerItem)
    }

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

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0.0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return interitemSpace
    }
}

1
거기에서 대중을 제거 할 수 있다고 생각하십시오. 잘 작동하고 다른 모든 기능과 일치해야합니다.
— Edward Potter

세로 스크롤 모음보기에서 작동합니까? iPhone 6s 및 6s Plus와 같은 장치에서 가로로 2 개의 셀을 표시 해야하는 컬렉션보기가 있지만 그보다 낮은 것, 즉 5s, 5 및 SE에 대해서는 하나의 셀만 표시해야합니다. 현재 코드는 작동하지만 6s Plus 장치에서는 셀 사이의 간격이 너무 커서 추악하게 보이고 그 간격을 줄이기 위해 노력하고 있으며 다른 모든 장치가 내 디자인에 따라 작동하기 때문에 이것이 유일한 요구 사항입니다.
— AnBisw

11

간격을위한 간단한 코드

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 10 // Some float value

3
가로 셀 간격의 경우 minimumLineSpacing
— Alfi

9

투표 대답 (또한 빠른 버전 ) 작은 문제를 가지고 : 오른쪽에 큰 간격이있을 것이다.

플로우 레이아웃은 플로트가 왼쪽 인 셀 간격이 정확하도록 사용자 정의되기 때문입니다 동작으로 입니다.

내 해결책은 섹션 삽입을 조작하여 섹션이 가운데에 정렬되도록하지만 간격이 정확히 지정된 것입니다.

아래 스크린 샷에서 항목 / 줄 간격은 정확히 8pt이며 왼쪽 및 오른쪽 삽입 부분은 8pt보다 큽니다 (중앙 정렬되도록).

균일 한 간격의 셀

스위프트 코드는 다음과 같습니다.

private let minItemSpacing: CGFloat = 8
private let itemWidth: CGFloat      = 100
private let headerHeight: CGFloat   = 32

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Create our custom flow layout that evenly space out the items, and have them in the center
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
    layout.minimumInteritemSpacing = minItemSpacing
    layout.minimumLineSpacing = minItemSpacing
    layout.headerReferenceSize = CGSize(width: 0, height: headerHeight)

    // Find n, where n is the number of item that can fit into the collection view
    var n: CGFloat = 1
    let containerWidth = collectionView.bounds.width
    while true {
        let nextN = n + 1
        let totalWidth = (nextN*itemWidth) + (nextN-1)*minItemSpacing
        if totalWidth > containerWidth {
            break
        } else {
            n = nextN
        }
    }

    // Calculate the section inset for left and right. 
    // Setting this section inset will manipulate the items such that they will all be aligned horizontally center.
    let inset = max(minItemSpacing, floor( (containerWidth - (n*itemWidth) - (n-1)*minItemSpacing) / 2 ) )
    layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)

    collectionView.collectionViewLayout = layout
}

1
'NSInvalidArgumentException'이 발생합니다. 이유 : '*** setObjectForKey : object는 nil 일 수 없습니다 (키 : <NSIndexPath : 0xc000000000000016> {length = 2, path = 0-0})'catch되지 않은 예외입니다.
— DaftWooly 2016 년

... 내가 실수하지 않으면 while 루프는 다음과 같습니다. let n = Int((containerWidth + minItemSpacing)/((itemWidth+minItemSpacing)))
— DaftWooly

코드를 그대로 사용하지 않았지만 컬렉션 뷰에 대한 아웃 플로우 레이아웃을 구현하는 데 가장 적합한 참조를 제공했습니다. 건배
— Dima Gimburg

8

UICollectionViewDelegateFlowLayout헤더 파일에서 프로토콜을 정의하십시오 .

다음과 같은 UICollectionViewDelegateFlowLayout프로토콜 방법을 구현 하십시오.

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(5, 5, 5, 5);
}

여기 를 클릭 하여 Apple UIEdgeInsetMake방법 설명서를보십시오 .


3

실제 셀 크기를 건드리지 않고 간격을 조정하려면 이것이 가장 효과적입니다. #xcode 9 # tvOS11 # iOS11 #swift

따라서 UICollectionViewDelegateFlowLayout 에서 다음 메소드를 구현 변경하면 트릭은 두 가지를 모두 사용해야하며 문서는 실제로 그 방향으로 생각하도록 지시하지 않았습니다. :디

open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return cellSpacing
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return cellSpacing
}

3

스토리 보드 접근법

스토리 보드에서 CollectionView를 선택하고 크기 관리자로 이동하여 셀과 선의 최소 간격을 5로 설정하십시오.

프로그래밍 방식으로 스위프트 5

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let width = UIScreen.main.bounds.width / 4
        let height = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: width, height: height)

        //For Adjusting the cells spacing
        layout.minimumInteritemSpacing = 5
        layout.minimumLineSpacing = 5

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()

2

모노 터치를 사용하고 있으므로 이름과 코드가 약간 다르지만 collectionview의 너비가 (x * cell width) + (x-1) * x = amount의 MinimumSpacing과 같아야합니다. 행당 셀 수

MinimumInteritemSpacing 및 셀 너비에 따라 다음 단계를 수행하십시오.

1) 셀 크기 + 현재 삽입 + 최소 간격을 기반으로 행당 항목 수를 계산합니다.

float currentTotalWidth = CollectionView.Frame.Width - Layout.SectionInset.Left - Layout.SectionInset.Right (Layout = flowlayout)
int amountOfCellsPerRow = (currentTotalWidth + MinimumSpacing) / (cell width + MinimumSpacing)

2) 이제 컬렉션보기의 예상 너비를 계산하는 모든 정보가 있습니다.

float totalWidth =(amountOfCellsPerRow * cell width) + (amountOfCellsPerRow-1) * MinimumSpacing

3) 현재 너비와 예상 너비의 차이는

float difference = currentTotalWidth - totalWidth;

4) 이제 삽입을 조정하십시오 (이 예제에서는 오른쪽에 추가하여 collectionview의 왼쪽 위치가 동일하게 유지됨)

Layout.SectionInset.Right = Layout.SectionInset.Right + difference;

2

수평 UICollectionView및 하위 클래스가 있습니다.UICollectionViewFlowLayout 있습니다. 컬렉션보기에는 큰 셀이 있으며 한 번에 한 행만 표시되며 컬렉션보기는 화면 너비에 맞습니다.

나는 iago849의 대답을 시도했지만 효과가 있었지만 그의 대답이 필요하지 않다는 것을 알았습니다. 어떤 이유로 든 설정하면 minimumInterItemSpacing아무것도하지 않습니다. 내 항목 / 셀 사이의 간격은 다음과 같이 완전히 제어 할 수 있습니다minimumLineSpacing .

왜 이런 식으로 작동하는지 확실하지 않지만 작동합니다.


1
사실 "줄"값은 실제로 가로 레이아웃의 경우 항목 사이의 구분 기호입니다.
— Fattie

안녕하세요 @ user3344977-좋은 찾기. 이 문제를 가로 스크롤 모음보기를 직접 다루는 별도의 질문으로 분리하여 일부 사람들이 쉽게 찾을 수 있도록 결정했습니다. 나는 거기에 당신의 대답을 참조하십시오. 내 질문은 여기에 있습니다 : stackoverflow.com/q/61774415/826946
— Andy Weinstein

1

OP와 비슷한 문제를 발견했습니다. 불행히도 수락 된 답변은 내용이 collectionView올바르게 중앙에 배치되지 않았기 때문에 저에게 효과 가 없었습니다. 따라서 나는 다른 솔루션을 생각해 냈지만의 모든 항목 collectionView이 같은 너비 를 갖기 만하면 문제의 경우처럼 보입니다.

#define cellSize 90

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    float width = collectionView.frame.size.width;
    float spacing = [self collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section];
    int numberOfCells = (width + spacing) / (cellSize + spacing);
    int inset = (width + spacing - numberOfCells * (cellSize + spacing) ) / 2;

    return UIEdgeInsetsMake(0, inset, 0, inset);
}

이 코드는에 의해 반환 된 값 ...minimumInteritemSpacing...이 모든 사이의 정확한 간격이 collectionViewCell되도록하고 셀이 모두 중앙에 집중되도록 보장합니다.collectionView


꽤 괜찮은데. 그러나 비슷한 솔루션이 요소 사이의 수직 간격에 적용될 수 있는지 궁금합니다.
— p0lAris

가로 스크롤이있는 경우 세로 간격?
— luk2302 2016

1

위의 솔루션 으로 vojtech-vrbka은 정확하지만 경고를 트리거 :

경고 : UICollectionViewFlowLayout이 인덱스 경로에 대해 캐시 된 프레임 불일치를 캐시했습니다. 캐시 된 값 : 플로우 레이아웃 서브 클래스 Layout이 UICollectionViewFlowLayout에 의해 리턴 된 속성을 복사하지 않고 수정하므로 발생합니다.

다음 코드는이를 수정해야합니다.

class CustomViewFlowLayout : UICollectionViewFlowLayout {

   let cellSpacing:CGFloat = 4

   override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
       let original = super.layoutAttributesForElementsInRect(rect)

       if let original = original {
           let attributes = NSArray.init(array: original, copyItems: true) as! [UICollectionViewLayoutAttributes]

           for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
       }
       return nil
   }
}

2
이 접근법을 사용하는 SO에 대한 다른 답변과 마찬가지로 이것은 collectionView의 너비에 걸쳐 셀을 맞추는 데 효과적이지만 간헐적 인 가변 높이 간격은 여전히 ​​행 사이에 남아 있습니다. 이것은 CollectionView가 실제로 렌더링하는 방식의 한계 일 수 있습니다.
— Womble

1

스위프트 3 버전

UICollectionViewFlowLayout 서브 클래스를 작성하고이 메소드를 붙여 넣기 만하면됩니다.

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let answer = super.layoutAttributesForElements(in: rect) else { return nil }

        for i in 1..<answer.count {
            let currentAttributes = answer[i]
            let previousAttributes = answer[i - 1]

            let maximumSpacing: CGFloat = 8
            let origin = previousAttributes.frame.maxX

            if (origin + maximumSpacing + currentAttributes.frame.size.width < self.collectionViewContentSize.width && currentAttributes.frame.origin.x > previousAttributes.frame.origin.x) {
                var frame = currentAttributes.frame
                frame.origin.x = origin + maximumSpacing
                currentAttributes.frame = frame
            }
        }

        return answer
}

이것은 가로 맞춤에 적용되지만 minimumLineSpacingForSectionAt가 0을 반환하고 layout.minimumLineSpacing이 0으로 설정되어 있어도 행 사이에 간격이 유지됩니다. 또한 collectionView를 터치하면 첫 번째 루프가 종료되어 앱이 중단됩니다 범위의.
— Womble

1

나는 iago849의 답변을 시도했지만 효과가있었습니다.

스위프트 4

open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    guard let answer = super.layoutAttributesForElements(in: rect) else {
        return nil
    }
    let count = answer.count
    for i in 1..<count {
        let currentLayoutAttributes = answer[i]
        let prevLayoutAttributes = answer[i-1]
        let origin = prevLayoutAttributes.frame.maxX
        if (origin + CGFloat(spacing) + currentLayoutAttributes.frame.size.width) < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x {
            var frame = currentLayoutAttributes.frame
            frame.origin.x = origin + CGFloat(spacing)
            currentLayoutAttributes.frame = frame
        }
    }
    return answer
}

다음은 github 프로젝트의 링크입니다. https://github.com/vishalwaka/MultiTags


0

이전 버전은 실제로 섹션 1에서 작동하지 않았습니다. 그래서 내 솔루션은 여기에서 발견되었습니다. https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/ . 게으른 사람들을 위해 :

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
    var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
    // use a value to keep track of left margin
    var leftMargin: CGFloat = 0.0;
    for attributes in attributesForElementsInRect! {
        let refAttributes = attributes 
        // assign value if next row
        if (refAttributes.frame.origin.x == self.sectionInset.left) {
            leftMargin = self.sectionInset.left
        } else {
            // set x position of attributes to current margin
            var newLeftAlignedFrame = refAttributes.frame
            newLeftAlignedFrame.origin.x = leftMargin
            refAttributes.frame = newLeftAlignedFrame
        }
        // calculate new value for current margin
        leftMargin += refAttributes.frame.size.width + 10
        newAttributesForElementsInRect.append(refAttributes)
    }

    return newAttributesForElementsInRect
}

0

수락 된 답변에 문제가있어서 업데이트했습니다.

.h

@interface MaxSpacingCollectionViewFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) CGFloat maxCellSpacing;
@end

.미디엄

@implementation MaxSpacingCollectionViewFlowLayout

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    if (attributes.count <= 0) return attributes;

    CGFloat firstCellOriginX = ((UICollectionViewLayoutAttributes *)attributes[0]).frame.origin.x;

    for(int i = 1; i < attributes.count; i++) {
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        if (currentLayoutAttributes.frame.origin.x == firstCellOriginX) { // The first cell of a new row
            continue;
        }

        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        CGFloat prevOriginMaxX = CGRectGetMaxX(prevLayoutAttributes.frame);
        if ((currentLayoutAttributes.frame.origin.x - prevOriginMaxX) > self.maxCellSpacing) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = prevOriginMaxX + self.maxCellSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }
    return attributes;
}

@end

0

Swift 3Instagram과 같은 셀 라인 간격 내 솔루션 :

여기에 이미지 설명을 입력하십시오

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = UIColor.rgb(red: 227, green: 227, blue: 227)
    cv.showsVerticalScrollIndicator = false
    layout.scrollDirection = .vertical
    layout.minimumLineSpacing = 1
    layout.minimumInteritemSpacing = 1
    return cv
}()

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

    switch UIDevice.current.modelName {
    case "iPhone 4":
        return CGSize(width: 106, height: 106)
    case "iPhone 5":
        return CGSize(width: 106, height: 106)
    case "iPhone 6,7":
        return CGSize(width: 124, height: 124)
    case "iPhone Plus":
        return CGSize(width: 137, height: 137)
    default:
        return CGSize(width: frame.width / 3, height: frame.width / 3)
    }
}

프로그래밍 방식으로 장치를 감지하는 방법 : https://stackoverflow.com/a/26962452/6013170


0

가로 모음보기를 만드는 경우 셀 사이에 공간을 제공하려면 속성을 설정해야합니다 minimumLineSpacing.


-1

이 방법으로 놀아보십시오.

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                    layout:(UICollectionViewLayout*)collectionViewLayout
    insetForSectionAtIndex:(NSInteger)section {

    UIEdgeInsets insets = UIEdgeInsetsMake(?, ?, ?, ?);

    return insets;
}

2
이것은 셀이 아닌 섹션 사이의 간격에만 적용됩니다
— .
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.