UICollectionView интервалы полей

181

У меня есть, UICollectionViewкоторый показывает фотографии. Я создал коллекцию с помощью UICollectionViewFlowLayout. Это хорошо работает, но я хотел бы иметь интервалы на полях. Можно ли сделать это с помощью UICollectionViewFlowLayoutили я должен реализовать свой собственный UICollectionViewLayout?

Mert
источник

Ответы:

333

Вы можете использовать collectionView:layout:insetForSectionAtIndex:метод для вашего UICollectionViewили установить sectionInsetсвойство UICollectionViewFlowLayoutобъекта, прикрепленного к вашему UICollectionView:

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

или

UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setSectionInset:UIEdgeInsetsMake(top, left, bottom, right)];

Обновлено для Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
источник
35
Мне кажется, что я не получаю левую и правую вставки для работы при использовании вертикального макета потока ...
Джон
1
Теперь переопределение метода sectionInset для подкласса UICollectionViewFlowLayout также не имеет никакого эффекта. Установка свойства, описанного ниже, работает.
Дрен
4
NB: не забудьте добавить UICollectionViewDelegateFlowLayoutв свой список делегатов ViewController, чтобы использовать методinsetForSectionAtIndex
Дэвид Дуглас
98

Настройка вставок в Интерфейсном Разработчике, как показано на скриншоте ниже

Установка вкладок раздела для UICollectionView

Результатом будет что-то вроде этого:

Ячейка представления коллекции с разделом вставок

krzymar
источник
2
Отличный ответ, просто хотел отметить, что вам также придется играть с минимальным интервалом, чтобы вставка раздела работала хорошо.
Смит Яш
75

Чтобы добавить интервал на весь UICollectionView :

UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) collection.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(topMargin, left, bottom, right);

Чтобы поиграть с расстоянием между элементами одной строки (столбец, если вы прокручиваете по горизонтали) и их размерами:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
Marmor
источник
5
Это работает, но collection.collectionViewLayoutнуждается в приведении, как в примере @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj
Кастинг по-быстромуif let flow = collectionViewLayout as? UICollectionViewFlowLayout { flow.itemSize = CGSize(width: 100, height: 100) }
Эмили
41

Swift 4

    let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout // If you create collectionView programmatically then just create this flow by UICollectionViewFlowLayout() and init a collectionView by this flow.

    let itemSpacing: CGFloat = 3
    let itemsInOneLine: CGFloat = 3
    flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    let width = UIScreen.main.bounds.size.width - itemSpacing * CGFloat(itemsInOneLine - 1) //collectionView.frame.width is the same as  UIScreen.main.bounds.size.width here.
    flow.itemSize = CGSize(width: floor(width/itemsInOneLine), height: width/itemsInOneLine)
    flow.minimumInteritemSpacing = 3
    flow.minimumLineSpacing = 3

РЕДАКТИРОВАТЬ XCode 11.4 и Swift 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

не работает Используйте ниже работает.

let flow = UICollectionViewFlowLayout()

введите описание изображения здесь

Уильям Ху
источник
Есть ли способ установить цвет на расстояние?
Мартин Серрано
1
@ MartínDaniel Просто установите backgroundColorиз collectionView. Или какой бы супер вид.
Уильям Ху
1
но по краям полей нет
user924
@ user924 Поля по краям можно установить с помощью UIEdgeInsets (верх: слева: снизу: справа:). При вертикальной прокрутке установите левую / правую вставки. При горизонтальной прокрутке установите верхнюю и нижнюю вставки.
Марси
40

Просто чтобы исправить некоторую неправильную информацию на этой странице:

1- imumInteritemSpacing : минимальный интервал для использования между элементами в одной строке.

Значение по умолчанию: 10,0.

(Для сетки с вертикальной прокруткой это значение представляет минимальное расстояние между элементами в одной строке.)

2- imumLineSpacing : минимальный интервал для использования между линиями элементов в сетке.

Ссылка: http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewFlowLayout_class/Reference/Reference.html

Феликс
источник
2
Кажется, это не влияет на расстояние между разделами, только между элементами в одном разделе?
Crashalot
@Crashalot - ты уверен, что имеешь в виду минимумLineSpacing? т.е. каждая линия клеток? Есть также варианты для вкладок разделов, если вы действительно используете разделы.
Чаки
Это помогло мне сделать это через интерфейс раскадровки. Я искал решение для только горизонтальных представлений коллекции. Спасибо +10
призрак kemicofa
9

Modern Swift, автоматический расчет макета

Хотя эта ветка уже содержит кучу полезных ответов, я хочу добавить современную версию Swift , основанную на ответе Уильяма Ху. Это также улучшает две вещи:

  • Расстояние между разными линиями теперь всегда будет соответствовать расстоянию между элементами в одной строке.
  • Устанавливая минимальную ширину, код автоматически вычисляет количество элементов в строке и применяет этот стиль к макету потока.

Вот код:

// Create flow layout
let flow = UICollectionViewFlowLayout()

// Define layout constants
let itemSpacing: CGFloat = 1
let minimumCellWidth: CGFloat = 120
let collectionViewWidth = collectionView!.bounds.size.width

// Calculate other required constants
let itemsInOneLine = CGFloat(Int((collectionViewWidth - CGFloat(Int(collectionViewWidth / minimumCellWidth) - 1) * itemSpacing) / minimumCellWidth))
let width = collectionViewWidth - itemSpacing * (itemsInOneLine - 1)
let cellWidth = floor(width / itemsInOneLine)
let realItemSpacing = itemSpacing + (width / itemsInOneLine - cellWidth) * itemsInOneLine / max(1, itemsInOneLine - 1))

// Apply values
flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
flow.itemSize = CGSize(width: cellWidth, height: cellWidth)
flow.minimumInteritemSpacing = realItemSpacing
flow.minimumLineSpacing = realItemSpacing

// Apply flow layout
collectionView?.setCollectionViewLayout(flow, animated: false)
fredpi
источник
Если itemsInOneLineравно 1, то это приведет к NaN из-за деления на ноль здесь:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@TylerJames Спасибо! Я
исправил
8

использовать setMinimumLineSpacing:и setMinimumInteritemSpacing:на UICollectionViewFlowLayoutобъекте.

Джонатан Кишон
источник
Нет, это не работает, как ожидалось. setMinimumLineSpacing: Минимальный интервал для использования между элементами в одной строке. И setMinimumInteritemSpacing - это: минимальный интервал для использования между линиями элементов в сетке. Мой вопрос касается полей, а не пространства между элементами. например. Левый и верхний интервал первого элемента.
Мерт
Предполагая вертикальное направление srollDirection, вы можете использовать contentInset для верхнего и нижнего промежутка первого и последнего ряда. Также вы можете добавить свои поля в ваших ячейках.
Джонатан Кишон
8

Используя collectionViewFlowLayout.sectionInsetили collectionView:layout:insetForSectionAtIndex:правильно.

Однако, если ваш collectionView имеет несколько разделов и вы хотите добавить поле для всего collectionView, я рекомендую использовать scrollView contentInset:

UIEdgeInsets collectionViewInsets = UIEdgeInsetsMake(50.0, 0.0, 30.0, 0.0);
self.collectionView.contentInset = collectionViewInsets;
self.collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(collectionViewInsets.top, 0, collectionViewInsets.bottom, 0);
vmeyer
источник
5

Чтобы поместить пространство между CollectionItems используйте это

напишите эти две строки в viewdidload

UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(<CGFloat top>, <CGFloat left>, <CGFloat bottom>, <CGFloat right>)
Пуджа Джалан
источник
5

Установите insetForSectionAtсвойство UICollectionViewFlowLayoutобъекта, прикрепленного к вашемуUICollectionView

Обязательно добавьте этот протокол

UICollectionViewDelegateFlowLayout

стриж

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

Цель - С

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}
PinkeshGjr
источник
2

В Objective-C

CGFloat spacing = 5;
UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*)_habbitCollectionV.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(0, spacing, 0, spacing);
CGFloat itemsPerRow = 2;
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat oneMore = itemsPerRow + 1;
CGFloat width = screenRect.size.width - spacing * oneMore;
CGFloat height = width / itemsPerRow;

flow.itemSize = CGSizeMake(floor(height), height);
flow.minimumInteritemSpacing = spacing;
flow.minimumLineSpacing = spacing;

Все, что вам нужно сделать, это изменить значение itemsPerRow, и оно соответствующим образом обновит количество элементов в строке. Кроме того, вы можете изменить значение интервала, если хотите более или менее общий интервал.

введите описание изображения здесь введите описание изображения здесь

ScottyBlades
источник
1
Хорошо ... это отлично.
Сохил
1

Для добавления полей к указанным ячейкам вы можете использовать этот пользовательский макет потока. https://github.com/voyages-sncf-technologies/VSCollectionViewCellInsetFlowLayout/

extension ViewController : VSCollectionViewDelegateCellInsetFlowLayout 
{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAt indexPath: IndexPath) -> UIEdgeInsets {
        if indexPath.item == 0 {
            return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
        }
        return UIEdgeInsets.zero
    }
}
Myrddin
источник
0

В swift 4 и autoLayout вы можете использовать sectionInset следующим образом:

let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.itemSize = CGSize(width: (view.frame.width-40)/2, height: (view.frame.width40)/2) // item size
        layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10) // here you can add space to 4 side of item
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout) // set layout to item
        collectionView?.register(ProductCategoryCell.self, forCellWithReuseIdentifier: cellIdentifier) // registerCell
        collectionView?.backgroundColor = .white // background color of UICollectionView
        view.addSubview(collectionView!) // add UICollectionView to view
Мохен мохтари
источник
-1

Чтобы добавить 10px разделение между каждым разделом, просто напишите это

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Гал Бланк
источник
при использовании UICollectionReusableView вида UICollectionElementKindSectionFooter ваше решение не будет работать
Пратик Джамария,
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
Вишал
источник