如何在UICollectionView
的部分中设置单元格间距?我知道有一个属性minimumInteritemSpacing
我已将其设置为5.0仍然间距不会出现5.0。我已经实现了flowout委托方法。
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 5.0;
}
仍然没有得到理想的结果。我认为它的最小间距。我有没有办法设置最大间距?
答案 0 :(得分:183)
支持最初的问题。我试图在UICollectionView
上将间距设置为5px但这不起作用,以及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;
}
#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
答案 1 :(得分:133)
我知道这个话题已经过时了,但是如果有人仍然需要正确答案,那么你需要:
添加类似的实现:
- (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可以设置为您喜欢的任何值。这个技巧保证了单元格之间的空间完全等于maximumSpacing !!
答案 2 :(得分:69)
使用水平流布局,我在单元格之间也得到10个点间距。要删除我需要将minimumLineSpacing
以及minimumInterItemSpacing
设置为零所需的间距。
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.itemSize = CGSizeMake(cellWidth, cellHeight);
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 0;
flow.minimumLineSpacing = 0;
此外,如果所有单元格大小相同,则直接在流程布局上设置属性而不是使用委托方法更简单,更有效。
答案 3 :(得分:44)
请记住,它是最小行间距,而不是最小项间距或单元格空间。因为collectionView的滚动方向是 HORIZONTAL 。
如果它是垂直的,那么您需要为单元格之间的水平空间设置单元格空间或项目间空间,并为单元格之间的垂直空间设置行间距。
Objective-C版
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 20;
}
Swift版本:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}
答案 4 :(得分:34)
尝试使用此代码以确保每个项目之间的间距为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;
}
答案 5 :(得分:30)
Swift 版本最受欢迎的答案。单元格之间的空格将等于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
}
}
答案 6 :(得分:26)
我发现使用IB配置单元格或行之间的间距非常简单。
只需从storyboard / Xib文件中选择UICollectionView,然后单击下图中指定的尺寸检查器。
以编程方式配置空间使用以下属性。
1)用于在行之间设置空间。
[self.collectionView setMinimumLineSpacing:5];
2)用于在项目/单元格之间设置空间。
[self.collectionView setMinimumInteritemSpacing:5];
答案 7 :(得分:19)
请注意属性名称 minimumInterItemSpacing 。这将是项目 之间的 最小间距 ,而不是确切的 间距。如果将minimumInterItemSpacing设置为某个值,则可以确保间距不会小于该值。但是有机会获得更高的价值。
实际上,项目之间的间距取决于几个因素 itemSize 和 sectionInset 。集合视图根据这些值动态放置内容。所以你不能保证确切的间距。您应该使用 sectionInset 和 minimumInterItemSpacing 进行一些试验和错误。
答案 8 :(得分:14)
回答Swift 3.0,Xcode 8
1.确保设置了集合视图委托
class DashboardViewController: UIViewController {
@IBOutlet weak var dashboardCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
dashboardCollectionView.delegate = self
}
}
2.Implement UICollectionViewDelegateFlowLayout 协议,而不是UICollectionViewDelegate。
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
}
}
答案 9 :(得分:8)
voted answer(以及swift version)有一个小问题:右边会有很大的间距。
这是因为流量布局是自定义的,以使单元格间距准确, float left 行为。
我的解决方案是操作剖面插图,使剖面对齐居中,但间距完全符合指定。
在下面的屏幕截图中,项目/行间距正好是8pt,而剩下的部分是&amp;右边插入将大于8pt(使其居中对齐):
Swift代码如下:
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
}
答案 10 :(得分:8)
在头文件中定义UICollectionViewDelegateFlowLayout
协议。
实现UICollectionViewDelegateFlowLayout
协议的以下方法,如下所示:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(5, 5, 5, 5);
}
Click Here查看UIEdgeInsetMake
方法的Apple文档。
答案 11 :(得分:8)
间距的简单代码
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 10 // Some float value
答案 12 :(得分:2)
好吧,如果要创建水平集合视图,然后在单元格之间留出空间,则需要设置属性 $ isutf8 -il /bin/*
/bin/alias
/bin/bashbug
/bin/bashbug-64
/bin/bg
⋮
$ file -L $(isutf8 -il /bin/*)
/bin/alias: a /usr/bin/sh script, ASCII text executable
/bin/bashbug: a /usr/bin/sh - script, ASCII text executable, with very long lines
/bin/bashbug-64: a /usr/bin/sh - script, ASCII text executable, with very long lines
/bin/bg: a /usr/bin/sh script, ASCII text executable
⋮
。
答案 13 :(得分:2)
我正在使用monotouch,所以名称和代码会有所不同,但你可以通过确保collectionview的宽度等于(x * cell width)+(x-1)* MinimumSpacing with x =每行的细胞数量。
根据MinimumInteritemSpacing和Cell的宽度
执行以下步骤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)现在调整插图(在本例中我们将其添加到右侧,因此集合视图的左侧位置保持不变
Layout.SectionInset.Right = Layout.SectionInset.Right + difference;
答案 14 :(得分: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
答案 15 :(得分:1)
above solution 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
}
}
答案 16 :(得分:1)
如果你想在不触及实际单元尺寸的情况下调整间距,这就是最适合我的解决方案。 #xcode 9#tvOS11#iOS11 #swift
所以在 UICollectionViewDelegateFlowLayout 中,改变实现下一个方法,诀窍是你必须同时使用它们,文档并没有真正指向我思考这个方向。 :d
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
}
答案 17 :(得分:1)
Swift 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
}
答案 18 :(得分: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
答案 19 :(得分:0)
我对接受的答案有疑问,所以我更新了,这对我有用:
<强>·H 强>
@interface MaxSpacingCollectionViewFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) CGFloat maxCellSpacing;
@end
<强>的.m 强>
@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
答案 20 :(得分:0)
我在Swift 3
单元格行间距的解决方案,如Instagram:
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
答案 21 :(得分:0)
以前的版本并没有真正适用于&gt;部分所以我的解决方案在https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/找到了。对于懒惰的人:
SELECT Name,
CASE color
WHEN 'black' THEN 'b'
WHEN 'red' THEN 'r'
WHEN NULL THEN 'empty'
else 'n/a'
END AS Color_code
FROM SalesLT.Product;
答案 22 :(得分:0)
我有一个横向UICollectionView
和子类UICollectionViewFlowLayout
。集合视图有大单元格,一次只显示一行,集合视图适合屏幕宽度。
我尝试了iago849的答案并且有效,但后来我发现我甚至不需要他的答案。出于某种原因,设置minimumInterItemSpacing
不会做任何事情。我的项目/单元格之间的间距可以完全由minimumLineSpacing
控制。
不确定为什么它以这种方式工作,但它确实有效。
答案 23 :(得分:0)
在情节提要中选择CollectionView,然后转到大小检查器,并将单元格和线条的最小间距设置为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)
}()
答案 24 :(得分:0)
除了设置外,我所做的一切都很好:
layout.scrollDirection = .horizontal
答案 25 :(得分:-1)
尝试使用此方法:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
UIEdgeInsets insets = UIEdgeInsetsMake(?, ?, ?, ?);
return insets;
}