I am trying to create a custom table cell that will have rounded corners and a shadow. The end goal being to create a "card" look and feel. My storyboard setup is below. I created a separate view onto the content view of the cell so that I could manipulate that view to have the effects that I want. The problem is that the effects only seem to be affecting the top portion of the view. The bottom corners and not rounded and you can also see that the border is surrounding the entire view. I have included the custom cell class file as well. Any ideas on how to get the rest of the view to have the rounded corners and border?
class EventTableCell: UITableViewCell {
#IBOutlet weak var collectionView: UIView!
#IBOutlet weak var address: UILabel!
#IBOutlet weak var statusImage: UIImageView!
#IBOutlet weak var customerName: UILabel!
#IBOutlet weak var customerTime: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
//collectionView.backgroundColor = UIColor.gray
collectionView.clipsToBounds = false
collectionView.layer.cornerRadius = 10
collectionView.layer.borderWidth = 1
collectionView.layer.borderColor = UIColor.gray.cgColor
collectionView.layer.shadowColor = UIColor.lightGray.cgColor
collectionView.layer.shadowOpacity = 1
collectionView.layer.shadowOffset = CGSize.zero
collectionView.layer.shadowRadius = 3
}
}
Screen Shot of UiTableview in Main Storyboard:
Screen Shot of output:
Use this method:
extension UIView {
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
let backgroundCGColor = backgroundColor?.cgColor
backgroundColor = nil
layer.backgroundColor = backgroundCGColor
}
}
Call this method like this:
view.addShadow(offset: CGSize(width: 5, height: 5), color: .lightGray, radius: 5, opacity: 0.5)
You can call this method in the method 'awakeFromNib' of tableCell.
Note: Give proper height of table row also.
If your subviews of UICollectionView constraints are correct then set height automatic dimension in heightForRowAt and estimatedHeightForRowAt in UITableView delegate methods and reload the UICollectionView after start rendering.
Maintain some padding to all sides between cell contentView and containerView (*from your attached image) to visible shadow in all sides.
You can add following method where size will be yours preference and set "UICollectionViewDelegateFlowLayout" delegate to your class
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSize = CGSize(width: 100, height: 100)
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
let sectionInset = UIEdgeInsetsMake(10, 10, 10, 10)
return sectionInset
}
By applying these method you can able to display cell with proper way , currently your size of cell is exceeded then default size so this is happening , by implementing size method will remove default height and replace with your requested cell size.
Hope this will solve your problem.
Related
What is the way to set the equal size height for all cells in collection view?
I have this method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return getCellSize()
}
func getCellSize() -> CGSize {
let screenWidth: CGFloat = UIScreen.main.bounds.width
let spaceBetweenItems: CGFloat = CGFloat(2) * 10
let width: CGFloat = (screenWidth - 10 - spaceBetweenItems) / CGFloat(3.0)
return CGSize(width: width, height: CGFloat(140.0))
}
And these are my customs cell constraints:
This is my actual output:
What is wrong in my code or is missing one constraint ?
create Constraint CollectionViewHeight.
#IBOutlet weak var collectionViewHeight: NSLayoutConstraint!
and then, try this Code.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let height = collectionView.collectionViewLayout.collectionViewContentSize.height
collectionViewHeight.constant = height
self.view.layoutIfNeeded()
}
In storyboard with collection view: select your collection view -> go to size inspector -> change field "Estimate size" from "automatic" to "none"
like here.
But then if you text will be too large it will be clipped with dots like "Some large text..", so you can change field "Autoshrink" of your UILabel in attribute inspector to "Minimum Font Scale".
I have a horizontal collection view.
Each cell has a label and an image.
The problem that I am facing is that when label renders data from the server, sometimes the text is too big and overlaps the image because the width of each cell is fixed.
How can I change the width of the collection View view cell according to the data it contains so that the label does not overlap the image?
CollectionView does have a delegate method which returns cell size.
Please inherit UICollectionViewDelegateFlowLayout and implement the following method.
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 30, height: 30)
}
You can calculate your label width and return it to the function.
Hope this will help.
Calculate the width of the label text first with the font associated with the text.
extension String {
func size(with font: UIFont) -> CGSize {
let fontAttribute = [NSAttributedString.Key.font: font]
let size = self.size(withAttributes: fontAttribute)
return size
}
}
Return the calculated width along with collectionView height in collectionView(_, collectionViewLayout:_, sizeForItemAt)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Note: Margins are spaces around the cell
// model[indexPath.row].text is the text of label to be shown
let newWidth = model[indexPath.row].text.size(with: labelFont!).width + margins + imageView.width
return CGSize(width: newWidth, height: collectionView.bounds.height)
}
Note:
Don't forgot to confirm your viewController to UICollectionViewDataSource, UICollectionViewDelegateFlowLayout.
I have a UIImageView inside a ForecastCell Class (for a UICollectionView), anyhow, I can't get the UIImageView inside the cell to change it's size. This is what I tried:
private func setupWeatherIcon(){
self.addSubview(mWeatherIcon)
//mWeatherIcon.frame.size.width = CGFloat(self.frame.width) / 2
//mWeatherIcon.frame.size.height = CGFloat(self.frame.height) / 2
mWeatherIcon.frame.size.width = 20
mWeatherIcon.frame.size.height = 20
mWeatherIcon.centerXAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerXAnchor).isActive = true
mWeatherIcon.centerYAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerYAnchor).isActive = true
}
This is mWeatherIcon:
var mWeatherIcon: UIImageView = {
let image = UIImageView(image: UIImage(named: "partly-cloudy"))
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
No matter what width and height I set, It always stays the same width and height.
You need width and height constraints
self.contentView.addSubview(mWeatherIcon)
NSLayoutConstraint.activate([
mWeatherIcon.centerXAnchor.constraint(equalTo:contentView.centerXAnchor),
mWeatherIcon.centerYAnchor.constraint(equalTo:contentView.centerYAnchor),
mWeatherIcon.widthAnchor.constraint(equalTo:contentView.widthAnchor,multiplier:0.5),
mWeatherIcon.heightAnchor.constraint(equalTo:contentView.heightAnchor,multiplier:0.5)
])
Don't forget to implement this method
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
I have a collection view that the height of the cells won't change when I will run the application in bigger screen iPhone I used this code But when I will run this code I can't see my collection view in my app
remember that I have horizontal collection view that contains one line
var cellWidth:CGFloat = 0
var cellHeight:CGFloat = 0
var spacing:CGFloat = 12
var numberOfColumn:CGFloat = 9
//Scale Collection View
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
specialCollectionView.contentInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing)
if let flowLayout = specialCollectionView.collectionViewLayout as? UICollectionViewFlowLayout{
cellHeight = view.frame.size.height / specialCollectionView.frame.height
flowLayout.minimumLineSpacing = spacing
flowLayout.minimumInteritemSpacing = spacing
}
}
and here is the extension code
extension secondTabViewController:UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: cellWidth, height: cellHeight)
}
}
when i implement below code :
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
let cellW = (ScreenWidth - 10 - 10 - 30) / 4
return CGSize(width: cellW, height: cellW * 1.5 )
}
by using sizeForItemAt method , i can draw frame what i want , but my custom collectionview cell can not update as wise , where did i miss , plz help me !!
my custom cell
debug view
i fix it by this ref
UICollectionView cell subviews do not resize
thanks guys , at frist still have problem with my Cell.imageview , can not shape-round as i want , and i create a class for imageview ,below:
class CellImageView: UIImageView {
override func layoutSubviews() {
super.layoutSubviews()
let radius: CGFloat = self.bounds.size.width / 2.0
self.layer.cornerRadius = radius
self.clipsToBounds = true
}
and anything work perfectly
For me in iOS 13, I have fixed by first estimatedItemSize to .zero and set the itemSize like;
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.estimatedItemSize = .zero
layout.itemSize = CGSize(width: collectionView.frame.size.width, height: 80)
}