drop shadow around border of UITextView to give it 3d effect in iOS/swift - ios

Is there a way to drop a shadow around the border of a UITextView to give it a 3D effect? The textView has rounded corners.
I don't want to drop a shadow for the content of the textView (i.e. text). Just around the textView border only.
I need to clipToBounds on the textView for the rounded corners.
So far this is what I have tried:
let shadowLayer = CAShapeLayer()
shadowLayer.path = UIBezierPath(roundedRect: textView.bounds, cornerRadius: 15).cgPath
shadowLayer.fillColor = UIColor.clear.cgColor
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowOffset = CGSize(width: 2, height: 2)
shadowLayer.shadowOpacity = 1
shadowLayer.shadowRadius = 2
textView.layer.addSublayer(shadowLayer)
This results in:

Reason : Clips to bounds = true and shadow on the same view doest not work simultaneous. So to sort out this you have to do follow.
Add your TextView in a UIView (says viewTextBG).
TextView Constraints : top bottom, leading, trailing = 0 wrt. viewTextBG.
Give corner radius to textview and viewTextBG
textview.cornerRadius = 10
viewTextBG.cornerRadius = 10
Give clipsToBounds to textview and viewTextBG
textview.clipsToBounds = True
viewTextBG.clipsToBounds = false
Now give shadow to viewTextBG.
Now everything works, thats all.

Related

In iOS, how to have view with rounded corners and drop shadow mask its subview?

I'm trying to create something like this image except for those purple corners. Notice how the blue (shown as purple) contentView is not being clipped or masked by its parent containerView.
The requirements are to have a view which:
Has rounded corners.
Has a shadow.
It's subviews don't leak outside of it or its corners.
Here is the code I'm playing around with and I'm not sure exactly how to get this to work.
let containerView = UIView(frame: CGRect(x: 300, y: 100, width: 200, height: 200))
containerView.backgroundColor = .green
containerView.layer.cornerRadius = 40
containerView.layer.shadowRadius = 50
containerView.layer.shadowOffset = .zero
containerView.layer.shadowColor = UIColor.red.cgColor
containerView.layer.shadowOpacity = 1
view.addSubview(containerView)
let backgroundLayer = CALayer()
backgroundLayer.frame = containerView.layer.bounds
backgroundLayer.backgroundColor = UIColor.black.cgColor
backgroundLayer.opacity = 0.5
backgroundLayer.cornerRadius = containerView.layer.cornerRadius
backgroundLayer.masksToBounds = true
containerView.layer.addSublayer(backgroundLayer)
let contentView = UIView(frame: containerView.bounds)
contentView.backgroundColor = .blue
contentView.alpha = 0.3
// Omitting this line will produce a green square with rounded corners
// and a red shadow.
containerView.addSubview(contentView)
Based on this example code, one of my more specific questions is why doesn't the backgroundLayer which sets masksToBounds = true, mask the view's subview?
Based on this example code, one of my more specific questions is why doesn't the backgroundLayer which sets masksToBounds = true, mask the view's subview?
Because the subview is the subview of the view, not of the backgroundLayer.
Views are layers. Clipping is masking. A layer masks its own drawing and that of its sublayers. The subview's layer is not a sublayer of the backgroundLayer. It is its sibling, not its child. Your view/layer hierarchy looks like this:
containerView
| \
[layer] backgroundLayer
| (clips itself and its sublayers,
contentView but it has no sublayers)
|
[layer]

IOS Swift card effect image is getting clipped

Following is my code to create CardView and add shadow effect
override func awakeFromNib() {
super.awakeFromNib()
self.layoutIfNeeded()
cellBgview.layer.cornerRadius = 15.0
cellBgview.layer.borderWidth = 1.0
cellBgview.layer.borderColor = UIColor.clear.cgColor
cellBgview.layer.shadowColor = UIColor.gray.cgColor
cellBgview.layer.shadowRadius = 14.0
cellBgview.layer.shadowOpacity = 0.5
cellBgview.layer.shadowPath = UIBezierPath(roundedRect: cellBgview.bounds, cornerRadius: cellBgview.layer.cornerRadius).cgPath
// In
}
This looks like this
Corner radius not working in this case to make corner radius work I have added following code
cellBgview.clipsToBounds = true
After adding above code it looks this
Note that after adding cellBgview.clipsToBounds = true card elevation and shadow is missing but corner radius appears
How to make card view with corner radius and shadow without image getting clip.
Also tried
cellBgview.layer.masksToBounds = true
but it is not working.
Add another UIView in your cell and add imageView in that UIView...Apply corner radius to imageView. Apply shadow to that UIView holding imageView. add clipsToBounds to imageView not to that UIView because clipsToBounds clip anything outside bounds that can be shadow as well. will solve your issue
add a uiview in your cell, lets call it content view. in this view add another uiview in which you'll add the image view and your bottom labels. So actual hierarchy would look like this
--Cell
---UIView //add shadow on this view, also make its backgroundColor to clear color
---UIView //add corner radius to this view and clipsToBounds = true for this view
---UIImageView
---Bottom Labels / Another UIView / Stack View
this hierarchy will help you to achieve the image round corner only on top and view round corners on bottom content
Try this to achieve Shadow, Corner Radius, Border in one view.
cellBgview.backgroundColor = UIColor.white
let cellBgViewLayer = cellBgview.layer()
cellBgViewLayer?.masksToBounds = false
cellBgViewLayer?.shadowColor = UIColor.lightGray.cgColor
cellBgViewLayer?.shadowOpacity = 1.0
cellBgViewLayer?.shadowRadius = 6.0
cellBgViewLayer?.shadowOffset = CGSize(width: 0, height: 0)
cellBgViewLayer?.shouldRasterize = true
cellBgViewLayer?.cornerRadius = 5.0
cellBgViewLayer?.borderColor = UIColor.lightGray.cgColor
cellBgViewLayer?.borderWidth = 1.0
cellBgViewLayer?.shadowPath = UIBezierPath(rect: cellBgview.bounds).cgPath

How can i drop shadow to top and bottom of view which is inside the table view cell?

I have a view inside the table view cell and I want to show shadow to that view if below situations
if view on first cell then drop shadow to top, left, right.
if view on last cell then drop shadow to bottm, left, right.
other wise drop shadow only on left and right.
Thank You.
yourView.layer.shadowColor = UIColor.black.cgColor
yourView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
yourView.layer.shadowOpacity = 0.5
yourView.layer.shadowRadius = 2.0
And adapt the code below to the way you want for the corners that you'd like to drop shadow.
var shadowRect: CGRect = yourView.bounds.insetBy(dx: 0, dy: 4) // inset top and bottom of the cell
yourView.layer.shadowPath = UIBezierPath(rect: shadowRect).cgPath
put this code in your class
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.2
layer.shadowOffset = CGSize.zero
layer.shadowRadius = 5
}}
Then call it:--
YourView.dropShadow(scale: true)

Swift - UIView Containing UIImageView Containing Image

I'm trying to create a UIView that has a border color / width, add a subview UIImageView that has a different border color / width, and also has an image inside of all that. So essentially what I want is an image with a white border followed by a blue border.
Right now I'm only seeing the blue border show up. Here is what I am doing:
(Inside of a closure, where outerView is a UIView)
outerView.frame = cell.frame
outerView.layer.borderColor = UIColor.blue.cgColor
outerView.layer.borderWidth = 3.0
outerView.layer.cornerRadius = outerView.frame.height / 2
outerView.clipsToBounds = true
outerView.backgroundColor = UIColor.clear
let imageView = UIImageView(frame: outerView.frame)
imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self?.controller?.setupImageView(imageView, cell: cell)
outerView.addSubview(imageView)
(setupImageView:)
let frame = imageView.frame
imageView.image = imageConstants.imageToDisplay
imageView.clipsToBounds = true
imageView.layer.cornerRadius = frame.height / 2
imageView.layer.borderWidth = 3.0
imageView.layer.borderColor = UIColor.white.cgColor
If I change it up so the closure just returns me a UIImageView type (outerView is a UIImageView) and pass that straight into the setupImageView(imageView:cell:) function, I'm able to see the image along with a white border.
I'm not sure what I'm missing in order to get both to display.
Thank you in advance!
outerView and your imageView have the same frame (This mean they have the same height and the same width) the imageView's border is under the outherView's border.
Try this:
let outerFrame = outerView.frame
let frame = CGRect(x: outerFrame.origin.x - 3, y: outerFrame.origin.y - 3, width: outerFrame.size.width -6, height: outerFrame.size.height -6)
3 because borderWidth = 3.0
and:
let imageView = UIImageView(frame: frame)

Why I can't set the two top corners rounded in a UIView inside a UITableViewCell?

I can't set the two top corners rounded in a UIView inside a UITableViewCell, i.e.
let maskPath = UIBezierPath(roundedRect: containerView.bounds, byRoundingCorners: [.TopLeft, .TopRight, ], cornerRadii: CGSize(width: 10.0, height: 10.0))
let maskLayer = CAShapeLayer(layer: maskPath)
maskLayer.frame = containerView.bounds
maskLayer.path = maskPath.CGPath
maskLayer.masksToBounds = true
containerView.layer.mask = maskLayer
And when I run the app I get this:
I add background color to my custom UIView and background color to the cell content view just for demonstrative purpose and I added more value to the right constraint to show it doesn't work:
But If a create an UIView alone in an empty UIViewController it works perfectly.
I found when I set the fixed width adding a width constraint it works but I want the width size will be set dynamically (to work with all of the devices and orientations), adding trailing constraint is when it doesn't work.
Any ideas what I'm doing wrong?
I think it's working but what happens is that the width of your UIView is too large. (Bigger than your cell) so you don't see the right corner. Try to set some constraints on your UIView inside your cell and I think it will work

Resources