Як горизонтально центрувати клітини UICollectionView?


123

Я провів кілька досліджень, але не зміг знайти жодного прикладу коду щодо того, як централізувати клітини в UICollectionView по горизонталі.

замість того, щоб перша клітинка була подібно до цього X00 , я хочу, щоб вона була такою, як 0X0 . чи є спосіб досягти цього?

Редагувати:

щоб уявити, що я хочу:

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

Мені потрібно, щоб вона виглядала як версія B, коли у CollectionView є лише один елемент. Коли я отримав більше одного елемента, то це має бути як версія А, але з більшою кількістю елементів.

На даний момент це схоже на версію A, коли у мене є лише 1 елемент, і мені цікаво, як я можу зробити так, щоб він виглядав як B.

Дякую за допомогу!


Хіба не простіше дозволити клітинку відповідати ширині подання колекції, а потім централізувати подання колекції у своєму батьківському?
Артур Геворкян

так, є щонайменше два способи зробити це, спочатку (швидко) - це зробити ширину комірки на весь екран і відцентрувати його дочірній вигляд. другий (праворуч)
реалізуйте

Зрештою, з бекенда з'явиться більше комірок, заповнення всієї ширини не буде гарною ідеєю
RaptoX

збільшення ширини достатньо для встановлення в центрі
Kishore Kumar

Відповіді:


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
Анірудха Махале

5
У Swift 3 новий підпис методу є collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Камчатка

1
як ви можете захопити ширину стільникової комірки, чи це можливо за допомогою методу cellForItemAt? Я спробував, і він повернувся до нуля .. ширина комірки для мене змінюється залежно від розміру екрана .. @DarshanPatel.
Кріс,

10
@DarshanPatel. Ваша відповідь іноді може спричинити негативне значення на менших пристроях. Подумайте про те, щоб скористатись максимальною перевіркою вашої leftInsetвартості так:let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Rhuari Glen

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
Ахмед Сафаді

Ваша відповідь справно працює, якщо є комірки, які вміщуються в collectionView, коли кількість клітинок збільшується, клітини є центральними, і ви не можете прокручувати до першої комірки або останньої.
NickCoder

2
@Vitalii 80 означає ширину комірки та 10 проміжок між клітинками, якщо ви прочитаєте ім'я змінної, то зрозуміли б, що вона означає: P
Ахмед Сафаді

Рішення Swift 4.2 простіше, ДЯКУЄМО! Просто не забудьте встановити "80" будь-якої фактичної ширини об'єкта комірки.
Джон Піттс

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


1
це найкраща відповідь. З найпростішою математикою. працює з будь-якою кількістю рядків і стовпців
rickrvo

20

Для цього я використовую KTCenterFlowLayout , і він чудово працює. Це спеціальний підклас, UICollectionViewFlowLayoutякий центрирує клітинки так, як вам потрібно. (Примітка. Це не тривіальна річ для вирішення, розміщуючи якийсь код, саме тому я посилаюся на проект GitHub!)


Не вдалося змусити його працювати з IB. Ця бібліотека спрацювала як принадність для мене. Просто встановив стручок і змінив клас компонування в IB!
tagirkaZ

15

Об'єктивна версія відповіді Даршана Пателя :

- (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 для показу u знятого екрану. . але ви можете додати "yynoalzg" у крихітному URL-адресі. Ви отримаєте ідею. Золота секція має 4 записи. 4-й має бути в новому рядку. .але після цього методу він відображається так ... дайте мені знати, чи є якась ідея.
Гітарт

6

Трохи модифікуючи відповідь @Safad Funy, саме це працювало для мене в останній версії Swift & iOS. У цьому випадку я хотів, щоб ширина комірок становила третину розміру представлення колекції.

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
Це працювало для мене особливо, коли є лише одна комірка.
Дасога

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


Дійсно ваш код відмінно працює для мене, дякую чувак; )
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

Для людей, які хочуть лише додати прокладку ( зверху, зліва, знизу, праворуч ):

Додайте протокол 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менше , ніж CollectionViewх width, але тільки , щоб захиститися від цього ви можете зробити , як показано нижче.

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
}

Без назви-3.png


Що таке межі у швидкому коді? я отримую використання невирішеної помилки "межі" ідентифікатора
Sachin Tanpure

Привіт, у моєму прикладі я реалізував метод всередині UIView, у якого є межі, якщо ви реалізуєте його в іншому місці, використовуйте відповідні межі
Пітер Лапис

0

У мене схожа ситуація в проекті, і я виправив це, посилаючись UPCarouselFlowLayout

Я думаю, що це підтримка swift 5версії

https://github.com/ink-spot/UPCarouselFlowLayout/blob/master/UPCarouselFlowLayout/UPCarouselFlowLayout.swift

Подивіться на реалізацію коду в

override open func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint

0

найпростіший спосіб - встановити розмір кошторису подання колекції на None у раскадровці або з кодом 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

Я використовував цей код у проекті. Він центрує колекціюView по горизонталі та вертикалі в обох напрямках .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як мозаїчний приклад від Apple.


-3

Я думаю, що вам потрібно централізувати клітинку, тому замість використання collectionView я буду корисний для UITableView. Просто використовуйте UIViewController і помістіть два UIView спереду і ззаду і поставте UITableViewпосередині Надіюсь, що це допоможе


Я додав фотографію, щоб показати вам, що саме мені потрібно, дякую!
RaptoX
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.