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을 일부 값으로 설정하면 간격이 그보다 작은 값이되지 않도록 할 수 있습니다. 그러나 더 높은 가치를 얻을 가능성이 있습니다.

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


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.