我正在实现类似日历布局,并在屏幕截图中显示了一些修改。为实现这一点,我使用了UICollectionView。问题是,我必须绘制一个屏幕宽度连续线(截图中的绿线)。 The green line should cover the whole width
,我知道由于half of the cornerRadius
而没有在圆形单元格上显示,而在第一个单元格(上午10点)之后仅显示垂直线。我必须添加shapelayer,以便它看起来像一条连续的线。这是我到目前为止尝试过的代码。
KKViewController.m
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! KKBookCollectionViewCell
self.bookingCollectionView.backgroundColor = UIColor.whiteColor()
let rectangularRowIndex:NSInteger = indexPath.row % 5
if(rectangularRowIndex == 0 )
{
cell.userInteractionEnabled = false
cell.layer.cornerRadius = 0
cell.timeSlotLabel.text = "10am"
cell.backgroundColor = UIColor.whiteColor()
cell.layer.borderWidth = 0
cell.layer.borderColor = UIColor.clearColor().CGColor
}
else
{
cell.userInteractionEnabled = true
cell.layer.cornerRadius = cell.frame.size.width/2
cell.timeSlotLabel.text = ""
//cell.backgroundColor = UIColor.lightGrayColor()
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.grayColor().CGColor
if cell.selected == true
{
cell.backgroundColor = UIColor.greenColor()
}
else
{
cell.backgroundColor = UIColor.lightGrayColor()
}
}
return cell
}
KKCollectionCell.m
var borderWidth:CGFloat!
var borderPath:UIBezierPath!
override func awakeFromNib() {
super.awakeFromNib()
drawHorizontalLine()
dottedLine(with: borderPath, and: borderWidth)
drawVerticalLine()
dottedLine(with: borderPath, and: borderWidth)
func drawVerticalLine()
{
borderPath = UIBezierPath()
borderPath.moveToPoint(CGPointMake(self.frame.origin.x + self.frame.size.width, self.frame.origin.y))
//borderPath.addLineToPoint(CGPointMake(self.frame.size.width - 5, self.frame.origin.y + self.frame.size.height - 50))
borderPath.addLineToPoint(CGPointMake(self.frame.origin.x + self.frame.size.width, self.frame.origin.y + self.frame.size.height))
borderWidth = 2.0
print("border path is %f, %f:\(borderPath)")
}
func drawHorizontalLine()
{
borderPath = UIBezierPath()
borderPath.moveToPoint(CGPointMake(0, self.frame.origin.y))
borderPath.addLineToPoint(CGPointMake(self.frame.size.width + 10, self.frame.origin.y))
borderWidth = 2.0
print("border path is %f, %f:\(borderPath)")
}
func dottedLine (with path:UIBezierPath, and borderWidth:CGFloat)
{
let shapeLayer = CAShapeLayer()
shapeLayer.strokeStart = 0.0
shapeLayer.strokeColor = UIColor.greenColor().CGColor
shapeLayer.lineWidth = borderWidth
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineDashPattern = [1,2]
shapeLayer.path = path.CGPath
self.layer.addSublayer(shapeLayer)
}
答案 0 :(得分:0)
您可以在集合视图单元格中添加新视图,并为该新视图设置角半径。您还必须减少单元格之间的间距。然后这条线看起来就像你期望的那样。
答案 1 :(得分:0)
我知道这是一个老问题,但从未得到正确回答,我一直在寻找这种行为并在另一个答案的帮助下实现了它。 要实现这一点,您需要对 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
}
函数 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,所以这些线并不完全沿着屏幕,而是一些聚集在一起的线,看起来像一条完整的线,你可以调整它的宽度和高度,玩那个。
注意为布局中的属性设置的框架,即装饰视图的框架,并且是相对于单元格(属性)定义的。
不要忘记注册那个装饰视图,并制作布局并将其传递给 collecitonview,如下所示:
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