How can I get a pixel perfect one (1) pixel with border line in a UICollectionView (e.g. to make a month calendar). The issue is that where cells meet, their borders meet, so it is effectively 2 pixels (not 1 pixel).
Therefore this is a CollectionView layout related issue/question. As the way each cell puts it own 1 pixel border gives rise, when the cells all meet up with zero spacing, to what looks like a 2 pixels border overall (except for outer edges of the collectionView which would be 1 pixel)
Seeking what approach/code to use to solve this.
Here is the custom UICollectionViewCell class I use, and I put borders on the cells in here using drawrect.
import UIKit
class GCCalendarCell: UICollectionViewCell {
@IBOutlet weak var title : UITextField!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
override func drawRect(rect: CGRect) {
self.layer.borderWidth = 1
self.layer.borderColor = UIColor.redColor().CGColor
}
}
There are a few strategies you can take to solve this issue. Which is best depends on some of the details of your layout.
Draw borders of 1/2 the desired width around each item. This has been suggested. It achieves the correct width for borders between items, but the borders around the edge of the collection will also be half the desired width. To solve this you can draw a border around the entire collection, or sections.
If you're month layout only renders days in a given month, meaning each month has a unique non-rectangular shape, fixing the edge borders is more complicated than it's worth.
Draw the full border around each item but adjust the frames so they overlap by half of the width of the borders, hiding the redundancy.
This is the simplest strategy and works well, but be aware of a few things:
Rather than using borders on the cell at all, you can add a border around the container and then manually draw the borders in the superview. This could be accomplished by overriding drawRect(_:)
and using UIBezierPaths
to draw horizontal and vertical lines at the intervals of the cells. This is the most manual option. It gives you more control, but is much more work.
Rather than assigning the layer's border width and border color, which draws a border around the entire view, selectively draw edges of cells. For example: each cell could only draw it's bottom and right edge, unless there is no cell above or to the right of it.
This can again lead to complications if you have an irregular grid. It also requires each cell to know about it's context in the grid which requires more structure. If you go this route, I would suggest subclassing UICollectionViewLayoutAttributes
and adding additional information about which edges should be drawn. The edge drawing itself can again be done by creating UIBezierPath
's in drawRect(_:)
for each edge.
I usually divide the border width by the screen scale:
width = 1.0f / [UIScreen mainScreen].scale
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With