현재 UICollectionView
사용자 인터페이스 그리드를 사용하고 있으며 제대로 작동합니다. 그러나 가로 스크롤을 사용하고 싶습니다. 그리드는 페이지 당 8 개 항목을 지원하며 총 항목 수가 4 개일 때 가로 스크롤 방향이 활성화 된 상태에서 항목을 정렬하는 방법은 다음과 같습니다.
0 0 x x
0 0 x x
여기에 0-> 컬렉션 항목 및 x-> 빈 셀
다음과 같이 가운데 정렬하는 방법이 있습니까?
x 0 0 x
x 0 0 x
콘텐츠가 더 깔끔하게 보이도록?
또한 아래 배열이 내가 기대하는 해결책이 될 수도 있습니다.
0 0 0 0
x x x x
답변
다음과 같이 구현하면 한 줄 모양을 얻을 수 있다고 생각합니다.
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 100, 0, 0);
}
콘텐츠를 한 줄로 만드는 방법을 알아 내려면 해당 번호를 가지고 놀아야합니다. 첫 번째 0은 상단 가장자리 인수입니다. 화면에서 콘텐츠를 세로로 중앙에 배치하려면이 인수도 조정할 수 있습니다.
답변
중앙 정렬, 동적 너비 collectionview 셀 에 대한 솔루션을 찾는 사람들을 위해 왼쪽 정렬 버전 에 대한 Angel의 대답을 수정하여 UICollectionViewFlowLayout
.
CenterAlignedCollectionViewFlowLayout
// NOTE: Doesn't work for horizontal layout!
class CenterAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let superAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
// Copy each item to prevent "UICollectionViewFlowLayout has cached frame mismatch" warning
guard let attributes = NSArray(array: superAttributes, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
// Constants
let leftPadding: CGFloat = 8
let interItemSpacing = minimumInteritemSpacing
// Tracking values
var leftMargin: CGFloat = leftPadding // Modified to determine origin.x for each item
var maxY: CGFloat = -1.0 // Modified to determine origin.y for each item
var rowSizes: [[CGFloat]] = [] // Tracks the starting and ending x-values for the first and last item in the row
var currentRow: Int = 0 // Tracks the current row
attributes.forEach { layoutAttribute in
// Each layoutAttribute represents its own item
if layoutAttribute.frame.origin.y >= maxY {
// This layoutAttribute represents the left-most item in the row
leftMargin = leftPadding
// Register its origin.x in rowSizes for use later
if rowSizes.count == 0 {
// Add to first row
rowSizes = [[leftMargin, 0]]
} else {
// Append a new row
rowSizes.append([leftMargin, 0])
currentRow += 1
}
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + interItemSpacing
maxY = max(layoutAttribute.frame.maxY, maxY)
// Add right-most x value for last item in the row
rowSizes[currentRow][1] = leftMargin - interItemSpacing
}
// At this point, all cells are left aligned
// Reset tracking values and add extra left padding to center align entire row
leftMargin = leftPadding
maxY = -1.0
currentRow = 0
attributes.forEach { layoutAttribute in
// Each layoutAttribute is its own item
if layoutAttribute.frame.origin.y >= maxY {
// This layoutAttribute represents the left-most item in the row
leftMargin = leftPadding
// Need to bump it up by an appended margin
let rowWidth = rowSizes[currentRow][1] - rowSizes[currentRow][0] // last.x - first.x
let appendedMargin = (collectionView!.frame.width - leftPadding - rowWidth - leftPadding) / 2
leftMargin += appendedMargin
currentRow += 1
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + interItemSpacing
maxY = max(layoutAttribute.frame.maxY, maxY)
}
return attributes
}
}
답변
여기에있는 최고의 솔루션은 기본적으로 작동하지 않았으므로 흐름 레이아웃과 하나의 섹션 만있는 가로 스크롤 컬렉션보기에서 작동해야하는 이것을 생각해 냈습니다.
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
// Add inset to the collection view if there are not enough cells to fill the width.
CGFloat cellSpacing = ((UICollectionViewFlowLayout *) collectionViewLayout).minimumLineSpacing;
CGFloat cellWidth = ((UICollectionViewFlowLayout *) collectionViewLayout).itemSize.width;
NSInteger cellCount = [collectionView numberOfItemsInSection:section];
CGFloat inset = (collectionView.bounds.size.width - (cellCount * cellWidth) - ((cellCount - 1)*cellSpacing)) * 0.5;
inset = MAX(inset, 0.0);
return UIEdgeInsetsMake(0.0, inset, 0.0, 0.0);
}
답변
인세 트를 동적으로 계산하는 것은 쉽습니다.이 코드는 항상 셀을 중앙에 배치합니다.
NSInteger const SMEPGiPadViewControllerCellWidth = 332;
...
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
NSInteger numberOfCells = self.view.frame.size.width / SMEPGiPadViewControllerCellWidth;
NSInteger edgeInsets = (self.view.frame.size.width - (numberOfCells * SMEPGiPadViewControllerCellWidth)) / (numberOfCells + 1);
return UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.collectionView.collectionViewLayout invalidateLayout];
}
답변
다른 답변과 마찬가지로 이것은 정적 크기의 셀에서 작동해야하는 동적 답변입니다. 내가 만든 한 가지 수정 사항은 패딩을 양쪽에 넣는 것입니다. 이렇게하지 않으면 문제가 발생했습니다.
목표 -C
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
NSInteger numberOfItems = [collectionView numberOfItemsInSection:section];
CGFloat combinedItemWidth = (numberOfItems * collectionViewLayout.itemSize.width) + ((numberOfItems - 1) * collectionViewLayout.minimumInteritemSpacing);
CGFloat padding = (collectionView.frame.size.width - combinedItemWidth) / 2;
return UIEdgeInsetsMake(0, padding, 0, padding);
}
빠른
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let numberOfItems = CGFloat(collectionView.numberOfItems(inSection: section))
let combinedItemWidth = (numberOfItems * flowLayout.itemSize.width) + ((numberOfItems - 1) * flowLayout.minimumInteritemSpacing)
let padding = (collectionView.frame.width - combinedItemWidth) / 2
return UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding)
}
또한 여전히 문제가 발생하는 경우 이러한 값이 서로 관련되어있는 것처럼 보이기 때문에 minimumInteritemSpacing
및 모두 minimumLineSpacing
동일한 값으로 설정해야합니다 .
UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
flowLayout.minimumInteritemSpacing = 20.0;
flowLayout.minimumLineSpacing = 20.0;
답변
이것을 컬렉션 뷰 델리게이트에 넣으십시오. 다른 답변보다 기본 흐름 레이아웃 설정을 더 많이 고려하므로 더 일반적입니다.
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
NSInteger cellCount = [collectionView.dataSource collectionView:collectionView numberOfItemsInSection:section];
if( cellCount >0 )
{
CGFloat cellWidth = ((UICollectionViewFlowLayout*)collectionViewLayout).itemSize.width+((UICollectionViewFlowLayout*)collectionViewLayout).minimumInteritemSpacing;
CGFloat totalCellWidth = cellWidth*cellCount + spacing*(cellCount-1);
CGFloat contentWidth = collectionView.frame.size.width-collectionView.contentInset.left-collectionView.contentInset.right;
if( totalCellWidth<contentWidth )
{
CGFloat padding = (contentWidth - totalCellWidth) / 2.0;
return UIEdgeInsetsMake(0, padding, 0, padding);
}
}
return UIEdgeInsetsZero;
}
신속한 버전 (g0ld2k에게 감사) :
extension CommunityConnectViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
// Translated from Objective-C version at: http://stackoverflow.com/a/27656363/309736
let cellCount = CGFloat(viewModel.getNumOfItemsInSection(0))
if cellCount > 0 {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let cellWidth = flowLayout.itemSize.width + flowLayout.minimumInteritemSpacing
let totalCellWidth = cellWidth*cellCount + spacing*(cellCount-1)
let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right
if (totalCellWidth < contentWidth) {
let padding = (contentWidth - totalCellWidth) / 2.0
return UIEdgeInsetsMake(0, padding, 0, padding)
}
}
return UIEdgeInsetsZero
}
}
답변
왼쪽과 오른쪽에 패딩이 필요한 정적 크기의 컬렉션 뷰 셀에 대한 내 솔루션-
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let flowLayout = (collectionViewLayout as! UICollectionViewFlowLayout)
let cellSpacing = flowLayout.minimumInteritemSpacing
let cellWidth = flowLayout.itemSize.width
let cellCount = CGFloat(collectionView.numberOfItemsInSection(section))
let collectionViewWidth = collectionView.bounds.size.width
let totalCellWidth = cellCount * cellWidth
let totalCellSpacing = cellSpacing * (cellCount - 1)
let totalCellsWidth = totalCellWidth + totalCellSpacing
let edgeInsets = (collectionViewWidth - totalCellsWidth) / 2.0
return edgeInsets > 0 ? UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets) : UIEdgeInsetsMake(0, cellSpacing, 0, cellSpacing)
}