How can I add border to UICollectionView's cells which uses a custom UICollectionViewFlowLayout? When I override UICollectionView's flow layout, cell borders are "removed". how can I set borders properly?
Thank you!
I'm not sure how you want your border to look like, but whenever I need a quick border around a view, I usually use the following:
var view = UIView(frame: frame)
view.layer.borderWidth = 1
view.layer.borderColor = UIColor.blackColor().CGColor
Update Swift 3
view.layer.borderColor = UIColor.black.cgColor
You can either probably apply this to your collection view cell or create a custom class that sets these values after initialization.
Either that, or you can set the cell size so that spaces between cells serve as borders and set minimumLineSpacing and minimumInteritemSpacing in your custom flow layout implementation.
Related
I am trying to create rounded corners for a custom cell in my UITableView, I have tried the following.
let cell = tableView.dequeueReusableCell(withIdentifier: "FriendCell", for: indexPath)
let friend = friends[indexPath.row]
cell.textLabel?.text = friend.value(forKey: "name") as? String
cell.textLabel?.textAlignment = .center
cell.layer.cornerRadius = 12
cell.layer.borderColor = UIColor.red.cgColor
The result shows up like this, it is creating the border around the content view as opposed to the view for the cell. If anyone is able to help, it would be much appreciated. Thank you!
https://i.stack.imgur.com/mf1kk.png
If you want to modify the corner radius of cell you should work with contentView layer.
cell.contentView.layer.backgroundColor = UIColor.lightGray.cgColor
cell.contentView.layer.borderWidth = 1.5
cell.contentView.layer.cornerRadius = 12
cell.contentView.layer.borderColor = UIColor.red.cgColor
image of cell here
You set the borderColor and cornerRadius but you don’t set the borderWidth. With a zero border width (The default) you won’t get a border on your layer.
If you don’t set the fill color either, the layer also won’t get filled with a different color, and your change to the corner radius won’t have any visible effect.
I agree with #LucaPetra that you should really set the layer properties on the content view rather than the cell, but that shouldn’t prevent your code from working.
Also note that you need to make sure that you fully configure the layer properties on all of your cells, or you will get hard-to-debug cell reuse problems. (If only some of your cells get a border color/width, and you don’t set the border width to 0 on the cells that should not have a border width, sometimes you’ll get a recycled cell that still has a custom border width/color, and that border will show up on the recycled cell next time it’s used as a different cell type.
I have a collection view with rounded and shadow-dropped cells. The shadow of the cell suddenly disappears, instead of smoothly moving out of the view, when the cell is about to be covered by the navigation bar. Below is the code:
contentView.layer.cornerRadius = 20
contentView.layer.masksToBounds = true
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.1
layer.shadowOffset = CGSize(width: 0, height: 5.0)
layer.shadowRadius = 5.0
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius - 3).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
Here is the gif showing the problem. Focus on the shadow at the bottom of the cell. The navigation bar is white. Any help would be appreciated. Thank you!
Instead of setting shadow of contentView embed all your content in a UIView and set shadow of that view instead. Then you have to increase the height of your cell about 20 points or as much your shadow height. That should work I guess.
I believe it's simply because the cell does really get removed from the view, thus it's shadow goes with it. At that point the frame of the cell is out of the view, while shadow is still visible (shadow is around the frame) - but when the frame goes out of view, the collectionView removes the cell. And so the shadow disappears abruptly.
What I would do about it is very simple. I would refactor the code to wrap the current cell contents into a new UIView - lets call it wrapper, that will drop the shadow. Then put this wrapper into the cell's contentView so that the wrapper along with its shadow will fit inside of the contentView. Then the shadow will become a part of the contentView frame, which means that the shadow will disappear from the screen only when the whole cell is hidden.
Of course, you will have to modify the collectionView's size for cell, because now the cells will be bigger to contain also the shadow.
How would I change my cells in the UITableViewCells to have rounded corners? Kind of like this:
I like the gaps that are present, so is there away to adjust that as well?
In the ContentView of the UITableViewCell you can set, this lines the get the rounded corner.
self.layer.cornerRadius = 5.0
self.clipsToBounds = true
self.layer.masksToBounds = true
To give the gap, you need to set the default content view to Clear Color (to be transparent), and add a View inside the cell, with a smaller size then the cell.
It will look like this in the storyboard.
I want to center my cells horizontally in my table view. Currently, they stick to the left. How do I go about doing this?
I've looked up various questions on SO and webpages, but they're all in Objective C, and I use Swift.
You shouldn't try to center the cells of your table view. You should allow Cocoa to manage the size of your cells and you should center your content within the content view of the cell.
There are 2 things you need to do:
First, you need to make sure you set the table style to Default: UITableViewCellStyleDefault. All other styles use a detailTextLabel in one way or another and you won't be able to set the textLabel's alignment property.
UITableViewCell(style: .Default, reuseIdentifier: CellIdentifier)
Then you can set the alignment of your cell's textLabel:
cell.textLabel.textAlignment = .Center
There are two approaches as listed below
1- you have to create cell w.r.t tableview width but drag your cell content in centre from nib.
2- You have to decrease tableview size so your cell fit with tableview.
if don't subclass the tableview cell, then subclass the UITableViewCell
and just override below method,
in CustomCell add below method
override func layoutSubviews()
{
super.layoutSubviews()
self.frame = CGRectMake(self.frame.origin.x + 100, self.frame.origin.y, 100 , 100);
//option 2
// self.bounds = CGRectMake( 100,0, 100 , 100);//calculate centre
}
in above u must use current frame react and calculate the centre according to your requirement, as u see i use the current frame of the cell if u ignore this, the x and y position set to zero the cell is always at the (0,0,width,height) of the tableview
and also also u can also use bounds it worked i comment it as option 2
Due to our designer being a sadist, I have a UITableView with a segmented control that switches between two different types of cells in separate feeds. The cells are dequeued with different identifiers and classes — this all works fine. The cells share a parent but are different sizes and for optimization reasons I set the layer.shadowpath manually in layoutSubviews() of the parent. I need the shadows: designer's wishes.
The issue is that after I switch to the second segment, some of the way down the table there are shadows dangling from what I believe are the cells above. As you can see from the first image, there are two shadows, and if I scroll down to occlude the top-most visible cell the shadow disappears, which leads me to the believe that the shadows are offset. Further scrolling makes these shadows disappear and not reappear again until switching tabs again. The rest of the shadows are fine.
two shadows
scroll down slightly
When switching back to the previous tab, where the cells are taller, there are also shadow issues, but those shadows are too short. As noted, the code that sets the shadow path is in the parent class, and the parent class is responsible for making and laying-out the top-most "card" view that contains the custom subCells.
I do everything programmatically: setting up the views and the Autolayout. Currently cell heights are hard-coded.
I'm not sure what information is relevant as I am completely at a loss, so here is how I set the shadowPath.
override func layoutSubviews() {
super.layoutSubviews()
cardView.layer.shadowPath = UIBezierPath(rect: cardView.bounds).CGPath
}
For simplicity the card is layout out in the contentView with the following visual format:
"V:|-marginV-[card]-marginV-|"
"H:|-marginH-[card]-marginH-|"
For whatever reason, even though I was using separate classes and separate reuseIdentifiers, the first reused cells just out of the view port were still sized as the tall cells in the other segment. When I changed
let cell = tableView.dequeueReusableCellWithIdentifier(booksReuseIdentifier) as! ProfileBookCell
to include the indexPath as
let cell = tableView.dequeueReusableCellWithIdentifier(booksReuseIdentifier, forIndexPath: indexPath) as! ProfileBookCell the recycling issue was remedied and bounds were properly computed. I tried layoutIfNeeded in a dozen different places to no effect, but this fixed it.
I had the same exact problem and I tried the current marked solution but that, nor anything else seemed to work. After trying so many other things I finally tried moving my add shadow code inside the layoutSubviews function of my subclassed UITableViewCell and it finally worked! I think this worked because the cell's final size isn't always calculated properly until the layouSubviews call and it needs the proper size to draw the shadow.
override func layoutSubviews() {
super.layoutSubviews()
addShadow(cell: self)
}
private func addShadow(cell:UITableViewCell) {
cell.layer.shadowOffset = CGSize(width:1, height:1)
cell.layer.shadowColor = UIColor.black.cgColor
cell.layer.shadowRadius = 1
cell.layer.shadowOpacity = 0.6
cell.clipsToBounds = false
let shadowFrame: CGRect = (cell.layer.bounds)
let shadowPath: CGPath = UIBezierPath(rect: shadowFrame).cgPath
cell.layer.shadowPath = shadowPath
}