Ios 在uicollectionview中的单元格下方添加水平线
我正在实现一个日历布局,并进行了一些修改,如屏幕截图所示。为了实现这一点,我使用了UICollectionView。问题是,我必须在截图中画一条屏幕宽度连续的绿线。绿线应该覆盖整个宽度,我知道它不会显示在圆形单元格上,因为有一半的转弯半径,只有在第一个单元格上午10点之后才显示垂直线。我必须添加shapelayer,使它看起来像一条连续线。这是我迄今为止尝试过的代码 KKViewController.m KKCollectionCell.mIos 在uicollectionview中的单元格下方添加水平线,ios,swift,uicollectionview,cashapelayer,Ios,Swift,Uicollectionview,Cashapelayer,我正在实现一个日历布局,并进行了一些修改,如屏幕截图所示。为了实现这一点,我使用了UICollectionView。问题是,我必须在截图中画一条屏幕宽度连续的绿线。绿线应该覆盖整个宽度,我知道它不会显示在圆形单元格上,因为有一半的转弯半径,只有在第一个单元格上午10点之后才显示垂直线。我必须添加shapelayer,使它看起来像一条连续线。这是我迄今为止尝试过的代码 KKViewController.m KKCollectionCell.m 可以在“集合视图”单元中添加新视图,并设置该新视图的角
可以在“集合视图”单元中添加新视图,并设置该新视图的角半径。此外,还必须减小单元之间的间距。然后,线条将与您预期的一样。您可以在“集合视图”单元格中添加新视图,并设置新视图的角半径。此外,还必须减小单元之间的间距。然后这句话就会像你期望的那样。我知道这是一个老问题,但从来没有得到正确的回答,我一直在寻找这样的行为,并在另一个答案的帮助下实现了它。 要实现这一点,您需要对UICollectionViewFlowLayout进行子类化,也许一个简单的布局也可以,但我没有尝试
class HorizontalLineFlowLayout: UICollectionViewFlowLayout {
var insets: CGFloat = 10.0
static let lineWidth: CGFloat = 10.0
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }
var attributesCopy: [UICollectionViewLayoutAttributes] = []
for attribute in attributes {
attributesCopy += [attribute]
let indexPath = attribute.indexPath
if collectionView!.numberOfItems(inSection: indexPath.section) == 0 { continue }
let contains = attributes.contains { layoutAttribute in
layoutAttribute.indexPath == indexPath && layoutAttribute.representedElementKind == HorizontalLineDecorationView.kind
}
if !contains {
let horizontalAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: HorizontalLineDecorationView.kind, with: indexPath)
let width = indexPath.item == collectionView!.numberOfItems(inSection: indexPath.section) - 1 ?
attribute.frame.width + insets :
attribute.frame.width + insets * 1.5
let frame = CGRect(x: attribute.frame.minX, y: attribute.frame.minY, width: width, height: 0.5)
horizontalAttribute.frame = frame
attributesCopy += [horizontalAttribute]
}
}
return attributesCopy
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
func layoutAttributesForElements每次都被调用,它为指定的单元格和指定的帧生成行
您还需要装饰视图,该视图如下所示:
class HorizontalLineDecorationView: UICollectionReusableView {
static let kind = "HorizontalLineDecorationView"
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .gray
alpha = 0.2
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
一般来说,它只是一个在单元格后面的视图,分别指向它的indexPath,所以这些线并不都在屏幕上,而是一些聚集在一起的线,看起来像一条完整的线,你可以调整它的宽度和高度,玩这个游戏
请注意,为布局中的属性设置的框架,即装饰视图的框架,是相对于单元属性定义的
不要忘记注册装饰视图,并制作布局并将其传递给CollectionView,如下所示:
let layout = HorizontalLineFlowLayout()
layout.register(HorizontalLineDecorationView.self, forDecorationViewOfKind: HorizontalLineDecorationView.kind)
layout.minimumInteritemSpacing = 10.0
layout.minimumLineSpacing = 10.0
layout.sectionInset = .zero
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(DateCell.self, forCellWithReuseIdentifier: "month")
collectionView.delegate = monthDelegate
collectionView.dataSource = monthDelegate
collectionView.backgroundColor = .clear
最终的结果是我知道这是一个老问题,但从来没有得到正确的回答,我一直在寻找这样的行为,并在另一个答案的帮助下实现了它。 要实现这一点,您需要对UICollectionViewFlowLayout进行子类化,也许一个简单的布局也可以,但我没有尝试
class HorizontalLineFlowLayout: UICollectionViewFlowLayout {
var insets: CGFloat = 10.0
static let lineWidth: CGFloat = 10.0
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }
var attributesCopy: [UICollectionViewLayoutAttributes] = []
for attribute in attributes {
attributesCopy += [attribute]
let indexPath = attribute.indexPath
if collectionView!.numberOfItems(inSection: indexPath.section) == 0 { continue }
let contains = attributes.contains { layoutAttribute in
layoutAttribute.indexPath == indexPath && layoutAttribute.representedElementKind == HorizontalLineDecorationView.kind
}
if !contains {
let horizontalAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: HorizontalLineDecorationView.kind, with: indexPath)
let width = indexPath.item == collectionView!.numberOfItems(inSection: indexPath.section) - 1 ?
attribute.frame.width + insets :
attribute.frame.width + insets * 1.5
let frame = CGRect(x: attribute.frame.minX, y: attribute.frame.minY, width: width, height: 0.5)
horizontalAttribute.frame = frame
attributesCopy += [horizontalAttribute]
}
}
return attributesCopy
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
func layoutAttributesForElements每次都被调用,它为指定的单元格和指定的帧生成行
您还需要装饰视图,该视图如下所示:
class HorizontalLineDecorationView: UICollectionReusableView {
static let kind = "HorizontalLineDecorationView"
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .gray
alpha = 0.2
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
一般来说,它只是一个在单元格后面的视图,分别指向它的indexPath,所以这些线并不都在屏幕上,而是一些聚集在一起的线,看起来像一条完整的线,你可以调整它的宽度和高度,玩这个游戏
请注意,为布局中的属性设置的框架,即装饰视图的框架,是相对于单元属性定义的
不要忘记注册装饰视图,并制作布局并将其传递给CollectionView,如下所示:
let layout = HorizontalLineFlowLayout()
layout.register(HorizontalLineDecorationView.self, forDecorationViewOfKind: HorizontalLineDecorationView.kind)
layout.minimumInteritemSpacing = 10.0
layout.minimumLineSpacing = 10.0
layout.sectionInset = .zero
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(DateCell.self, forCellWithReuseIdentifier: "month")
collectionView.delegate = monthDelegate
collectionView.dataSource = monthDelegate
collectionView.backgroundColor = .clear
最终结果是尝试使用BringSubViewToFront您的意思是像self.layer.bringSubviewToFrontself.layer.AddSublayerShapelayer将UIView添加到单元格中,并设置UIView的背景和角半径,而不是单元格本身。尝试使用BringSubViewToFront您的意思是这样的吗self.layer.bringsubview到front self.layer.addsublayershapelayer将UIView添加到单元格中,并设置UIView的背景和拐角半径,而不是单元格本身。这就是问题所在,无法缩小单元格之间的空间缩小了最小发光材料间距吗?这就是问题所在,不能缩小单元格之间的间距你缩小了最小的发光材料间距?