I've collectionViewCell and want to drop shadow to it, also want to have rounded corners, but it seems impossibile, cause to drop shadow clipToBounds must be set to false, with that, I can't add rounded corners, is there any kind of a "hack" to achieve my target?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let countryCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MySubscribitionsCollectionViewCell
countryCell.layer.cornerRadius = 10
countryCell.layer.borderWidth = 1.0
countryCell.layer.borderColor = UIColor.lightGray.cgColor
countryCell.layer.backgroundColor = UIColor.white.cgColor
countryCell.layer.shadowColor = UIColor.black.cgColor
countryCell.layer.shadowOffset = CGSize(width: 2.0, height: 4.0)
countryCell.layer.shadowRadius = 10.0
countryCell.layer.shadowOpacity = 0.5
countryCell.clipsToBounds = false
}
You can use another view to cast the shadow
Something like that
let shadowView = UIView()
shadowView.layer.masksToBounds = false
// SET SHADOW
let mainView = UIView()
mainView.layer.cornerRadius = 10
mainView.layer.masksToBounds = true
shadowView.addSubview(mainView)
In the case of a cell, you can set the shadow on the cell itself, and set the rounding of the corners and your custom views on the contentView of collectionViewCell
Related
I want to cache a shadow path to make the performance of UITableView better.
I've read https://yalantis.com/blog/mastering-uikit-performance/ that
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
would stop offscreen shadows, however using the following function
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Cell data: \(data[indexPath.row])"
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
cell.imageView?.layer.shadowRadius = 8
cell.imageView?.layer.shadowOffset = CGSize(width: 3, height: 3)
cell.imageView?.layer.shadowOpacity = 0.5
cell.imageView?.layer.cornerRadius = 20
cell.imageView?.image = UIImage(named: "PlaceholderImage")
return cell
}
produces a result where some cells have the shadow and some don't.
How can I implement caching of shadow paths to all cells in a simple UITableView
The problem is these lines:
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
If the cell's imageView has never been assigned an image, its frame is .zero and so its bounds is .zero. So the shadowPath ends up with a cgPath that is just a point, and no shadow appears.
The way I would solve this is that I would not use the built-in imageView property at all. I'd use a custom cell class with my own image view whose frame I can control, instead of the built-in imageView which plays these sorts of tricks.
if let shadowPath = self.shadowPathCache {
cell.imageView?.layer.shadowPath = shadowPath
} else if let rect = cell.imageView?.bounds {
self.shadowPathCache = UIBezierPath(rect: rect).cgPath
cell.imageView?.layer.shadowPath = self.shadowPathCache
}
I'm making a little notes app in which i've added a textView inside each cell, when selecting a cell it scales itself to certain size so the textView is scaled too. Everything is fine except that the text inside the textView is also scaled and looks pretty bad.
Does anyone know how to prevent the text from resizing or how can i handle this issue?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! collectionViewCell3
cell.clipsToBounds = false
cell.layer.cornerRadius = 10
noteTextView[indexPath.item].frame = CGRect(x: 10, y: 10, width: cell.frame.width - 20, height: cell.frame.height - 20)
noteTextView[indexPath.item].delegate = self
noteTextView[indexPath.item].textContainer.maximumNumberOfLines = 10
noteTextView[indexPath.item].isScrollEnabled = false
noteTextView[indexPath.item].font = UIFont(name: "Noteworthy-Light", size: 12)
noteTextView[indexPath.item].text = items[indexPath.item]
cell.contentView.addSubview(noteTextView[indexPath.item])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
index = indexPath
notasCollectionView.isScrollEnabled = false
let cell = notasCollectionView.cellForItem(at: indexPath)
let desiredPointY = notasCollectionView.contentOffset.y + 350
let desiredPointX = notasCollectionView.center.x
let differenceX = desiredPointX - cell!.frame.midX
let differenceY = desiredPointY - cell!.frame.mid
let differenceHeight = 354 / (cell?.frame.height)!
var tt = CGAffineTransform(scaleX: 1.89304813, y: differenceHeight)
tt = tt.concatenating(CGAffineTransform(translationX: differenceX, y: differenceY))
UIView.animate(withDuration: 0.2, delay: 0.0, animations: {
self.notasCollectionView.bringSubviewToFront(cell!)
cell!.transform = tt
}, completion: { _ in
UIView.animate(withDuration: 0.2) {
cell?.layer.cornerRadius = 0
}
})
}
Here are the screenshots:
[![Screenshot 1][1]][1] [![Screenshot 2][2]][2]
[1]: https://i.stack.imgur.com/cYURo.png [2]: https://i.stack.imgur.com/LbDND.jpg
The problem is you are increasing the size of the text view but the font size is the same.
So you need to change the font size according to your scaling multiplier.
I have added view as a background for tableview cell and I am giving shadow for view. Here when I run tableview shadow does not coming properly, once I scroll down and up then shadow coming properly.
I have given shadow according to this answer answer
Code:
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowOffset = CGSize(width: -1, height: 1)
layer.shadowRadius = 1
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PlansTableViewCell
cell.containerView.dropShadow()
return cell
}
Before scrolling shadow coming like this:
after scrolling coming like below:
After running(before scrolling) also i need second image kind of output, Here Help me with the code.
Problem is here
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
bounds isn't correct at that time , try
call it from
override func layoutSubviews() {
super.layoutSubviews()
self.containerViewdropShadow()
}
or
cell.layoutIfNeeded()
cell.containerView.dropShadow()
I have written a code for making the cell border color change according to inStock or outStock , if it is inStock it will be red border else it would be green, but I it is not working for me, I put it in willDisplayCell and here is my code :
func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath){
cell.backgroundColor = UIColor.clear
cell.contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x:10,y: 5,width: self.view.frame.size.width - 20,height: 214))
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1,height: 1)
whiteRoundedView.layer.borderWidth = 2
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
if stock[indexPath.row] == "inStock" {
whiteRoundedView.layer.borderColor = UIColor.red.cgColor
}
else {
whiteRoundedView.layer.borderColor = UIColor.green.cgColor
}
}
Try to move your code into cellForRowAt method like that
cell.layer.masksToBounds = true
cell.layer.cornerRadius = 5
cell.layer.borderWidth = 2
cell.layer.shadowOffset = CGSize(width: -1, height: 1)
let borderColor: UIColor = (stock[indexPath.row] == "inStock") ? .red : .green
cell.layer.borderColor = borderColor.cgColor
You are adding your whiteRoundedView multiple time for each cell - as cell instances are reused.
You should only create this once (when creating UITableViewCell) - and then manipulate color of it after that in willDisplayCell function.
I would suggest creating custom UITableViewCell, but you can also avoid that problem by using view "tag" property and checking if it exists already.
I create a collectionView and I want to add shadow to every cell, I wrote this code
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! MyCollectionViewCell
cell.myLabel.text = self.items[indexPath.item]
cell.backgroundColor = UIColor.yellow
cell.layer.shadowColor = UIColor.black.cgColor
cell.layer.shadowOffset = CGSize(width: 3, height: 3)
cell.layer.shadowOpacity = 0.7
cell.layer.shadowRadius = 4.0
return cell
}
but this is the output
I want it be like this
UIView with rounded corners and drop shadow?
Your code will probably work if you also say:
cell.layer.masksToBounds = false
The reason is that a shadow is outside the layer's bounds, so if we are masking to the bounds, you won't see the shadow.