Ios 在uicollectionview中的单元格下方添加水平线

Ios 在uicollectionview中的单元格下方添加水平线,ios,swift,uicollectionview,cashapelayer,Ios,Swift,Uicollectionview,Cashapelayer,我正在实现一个日历布局,并进行了一些修改,如屏幕截图所示。为了实现这一点,我使用了UICollectionView。问题是,我必须在截图中画一条屏幕宽度连续的绿线。绿线应该覆盖整个宽度,我知道它不会显示在圆形单元格上,因为有一半的转弯半径,只有在第一个单元格上午10点之后才显示垂直线。我必须添加shapelayer,使它看起来像一条连续线。这是我迄今为止尝试过的代码 KKViewController.m KKCollectionCell.m 可以在“集合视图”单元中添加新视图,并设置该新视图的角

我正在实现一个日历布局,并进行了一些修改,如屏幕截图所示。为了实现这一点,我使用了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的背景和拐角半径,而不是单元格本身。这就是问题所在,无法缩小单元格之间的空间缩小了最小发光材料间距吗?这就是问题所在,不能缩小单元格之间的间距你缩小了最小的发光材料间距?