UIView Custom Class trigger either shadow or roundCorners/addCornerRadius but not both in swift 3 [duplicate] - ios

This question already has answers here:
UIView with rounded corners and drop shadow?
(35 answers)
Closed 4 years ago.
UIView Custom Class trigger only shadow. I want to display both shadow and rounded corner for specific edges.Here is my code. Any suggestions would be appreciated.
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
class CustomView: UIView {
override func layoutSubviews() {
self.shadowColor = UIColor.darkGray
self.shadowOffset = CGSize(width: 4, height: 4)
self.shadowOpacity = 0.5
self.shadowRadius = 6.0
//only rounded corners triggered in UI
self.backgroundColor = UIColor.white
self.roundCorners(corners: [.topRight, .bottomRight], radius: 15.0)
}
}
Thanks in advance

Use separate views for the shadow and the border. The base view is transparent and has the shadow. The border view clips any other subcontent that it has to its borders. See the code below.
// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor = UIColor.black.cgColor
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0
// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor = UIColor.black.cgColor
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true
baseView.addSubview(borderView)
// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds
borderView.addSubview(otherSubContent)

Use this function:-
func addShadow(view: UIView, corner: CGFloat) {
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowOpacity = 0.5
view.layer.shadowRadius = 2
view.layer.shadowOffset = CGSize(width: 1, height: 1)
view.layer.masksToBounds = false
view.layer.cornerRadius = corner
}

Related

Swift - Shadow for a irregular shape of a View

i am struggling to add shadow to a custom shape.
Here is a picture of what i want to construct:
(Dont mind the text and the symbol)
You can see the custom shape with the curved corner on the right and the rectangular shape on the left with shadow.
I am using UIView, and added corner to the left.
This is the code i have so far that shape the view correct:
View1.backgroundColor = .green //green color is just to see the shape well
let path = UIBezierPath(roundedRect:View1.bounds,
byRoundingCorners:[.topRight, .bottomRight],
cornerRadii: CGSize(width: self.frame.height/2, height: self.frame.height/2))
let maskLayer = CAShapeLayer()
I Have tried to add shadow to it, but the shadow does not apear.
Here is the code i have tried to add shadow:
View1.layer.masksToBounds = false
View1.layer.layer.shadowPath = maskLayer.path
View1.layer.shadowColor = UIColor.black.cgColor
View1.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
View1.layer.shadowOpacity = 0.5
View1.layer.shadowRadius = 1.0
How can you add shadow to this shape?
You can achieve this by using a single UIView (shadowView), adding a shapeLayer sublayer and setting the shadow of the shadowView's layer.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
#IBOutlet var shadowView: UIView!
func setup() {
// setup irregular shape
let path = UIBezierPath.init(roundedRect: shadowView.bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize.init(width: 20, height: 20))
let layer = CAShapeLayer.init()
layer.frame = shadowView.bounds
layer.path = path.cgPath
layer.fillColor = UIColor.white.cgColor
layer.masksToBounds = true
shadowView.layer.insertSublayer(layer, at: 0)
// setup shadow
shadowView.layer.shadowRadius = 8
shadowView.layer.shadowOpacity = 0.2
shadowView.layer.shadowOffset = CGSize.init(width: 0, height: 2.5)
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowPath = path.cgPath
}
}
Note:
The shadowView.clipToBounds must be false for the shadows to take effect.
To see the layer.fillColor, set the shadowView.backgroundColor to .clear.
You can easily achieve the above via Interface Builder by setting the 'Background' property and unchecking the 'Clip to Bounds' checkbox.

Here corner is working but shadow is not work in iOS 9 and 10

Here corner is working but shadow is not work in iOS 9 and 10
and iOS 11 both are working fine
viewBlueMe.chatCellDesign([.topLeft,.bottomLeft,.topRight], [.layerMinXMinYCorner,.layerMinXMaxYCorner,.layerMaxXMinYCorner], radius: 5)
extenstion :
extension UIView {
func chatCellDesign(_ corners:UIRectCorner,_ cormerMask:CACornerMask, radius: CGFloat) {
if #available(iOS 11.0, *){
self.clipsToBounds = false
self.layer.cornerRadius = radius
self.layer.maskedCorners = cormerMask
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOpacity = 1
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 5
}else{
let rectShape = CAShapeLayer()
rectShape.bounds = self.frame
rectShape.position = self.center
rectShape.path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
self.layer.mask = rectShape
// FIXME: THIS CODE IS NOT WORK
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOpacity = 1
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 5
}
}
}
i need this type of output in iOS 9 and 10 also this is iOS11
Thanks in advance
Create one outerview and place your UILabel inside it, and please find below details,
outerView.layer.cornerRadius = 5.0
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowOpacity = 0.2
outerView.layer.shadowRadius = 5.0
UPDATE
See below image,
and this is IBOutlets
#IBOutlet weak var tmpView: UIView!
#IBOutlet weak var innerView: UIView!
You can do this way,
innerView.roundCorners([.topLeft, .topRight, .bottomLeft], radius: 5)
tmpView.layer.shadowColor = UIColor.black.cgColor
tmpView.layer.shadowOffset = CGSize.zero
tmpView.layer.shadowOpacity = 0.2
tmpView.layer.shadowRadius = 10.0
Find UIView extension here,
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
this will give you below output,
FYI. Play around shadow property for exact output you want.

How To Add Border To a UIView With Mask?

Here's what I need to do to my two buttons.
and here's what I got right now.
What I'm doing:
- Set these up in IB inside a stackView.
- Add masks
- Add borders with width and color
- Add shadow.
The borders are being added but being cut-off as well by the masks.
Codes:
public func addCornerRadiusToCorners(
_ corners: UIRectCorner,
cornerRadius: CGFloat,
borderColor: UIColor,
borderWidth: CGFloat) {
// self.layer.masksToBounds = true
// self.clipsToBounds = true
self.layer.borderWidth = borderWidth
self.layer.borderColor = borderColor.cgColor
let size = CGSize(width: cornerRadius, height: cornerRadius)
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size)
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
public func addDefaultShadow() {
let shadowPath = UIBezierPath(rect: self.bounds)
self.layer.masksToBounds = false
self.layer.shadowOffset = CGSize(width: 1, height: 1)
self.layer.shadowOpacity = 0.5
self.layer.shadowPath = shadowPath.cgPath
}
Any idea how to achieve the result in the first photo?
EDIT: the border is being cut, the result was just got from the UI Debugger of Xcode. Sorry.
Add corner radius to you view on viewDidAppear
#IBOutlet weak var segmentView: UIView!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
segmentView.layer.cornerRadius = segmentView.frame.size.height/2;
segmentView.layer.borderWidth = 1.0;
segmentView.clipsToBounds = true
segmentView.layer.borderColor = UIColor.lightGray.cgColor
segmentView.layer.shadowColor = UIColor.black.cgColor
segmentView.layer.shadowOpacity = 0.2
segmentView.layer.shadowRadius = 10.0
segmentView.layer.shadowOffset = CGSize(width: 1, height: 1)
segmentView.layer.masksToBounds = false
}
Sample Output:
you forgot to clip ur view.
self.clipsToBounds = true
you need to set maskstobounds to the view layer
segmentView.layer.masksToBounds = true

Chopped edge around border of image

I have an image with a border
let smallicon: UIImageView = {
let smallicon = UIImageView()
smallicon.layer.borderWidth = 2
smallicon.layer.borderColor = UIColor.whiteColor().CGColor
smallicon.hidden = true
return smallicon
}()
The problem is that is has tiny chopped edge around border (small image with yellow and black lines)
How to get rid of it ?
Solution
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Create a view with red background for demonstration
let v = UIView(frame: CGRectMake(0, 0, 100, 100))
v.center = view.center
v.backgroundColor = UIColor.redColor()
view.addSubview(v)
// Add rounded corners
let maskLayer = CAShapeLayer()
maskLayer.frame = v.bounds
maskLayer.path = UIBezierPath(roundedRect: v.bounds, byRoundingCorners: .TopRight | .TopLeft, cornerRadii: CGSize(width: 25, height: 25)).CGPath
v.layer.mask = maskLayer
// Add border
let borderLayer = CAShapeLayer()
borderLayer.path = maskLayer.path // Reuse the Bezier path
borderLayer.fillColor = UIColor.clearColor().CGColor
borderLayer.strokeColor = UIColor.greenColor().CGColor
borderLayer.lineWidth = 5
borderLayer.frame = v.bounds
v.layer.addSublayer(borderLayer)
}
}
NOTE! in order this to work target view must have frame property setup with size. without size your view will not be seen at all

How to add a shadow and CAShapeLayer to the same UIView

I'm trying to add a 6px radius to the bottom left and right corners of my view innerView, as well as a shadow to the whole of innerView. innerView is enclosed in a view called view2.
The only way I can get this to work is by using the following code:
let containerLayer = CALayer()
containerLayer.shadowColor = UIColor.blackColor().CGColor
containerLayer.shadowOffset = CGSizeMake(1, 2)
containerLayer.shadowOpacity = 0.2
containerLayer.shadowRadius = 2
let maskPath = UIBezierPath(roundedRect: innerView.bounds, byRoundingCorners: UIRectCorner.BottomLeft.union(.BottomRight), cornerRadii: CGSize(width: 6, height: 6)).CGPath
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath
innerView.layer.mask = maskLayer
containerLayer.addSublayer(innerView.layer)
view2.layer.addSublayer(containerLayer)
However, since view2 is actually the contentView of a UITableViewCell, this code disables scrolling of the UITableView when dragging on containerLayer...
Swift 4 :
This Code Helped Me To Drop A Shadow To UIVIEW And Add CornerRadious Using UIBezierPath. Set Your View's Background Color As ClearColor
yourView.backgroundColor=UIColor.clear
let path1 = UIBezierPath(roundedRect:yourView.bounds,
byRoundingCorners:[.topRight, .bottomLeft],
cornerRadii: CGSize(width: 20, height: 20))
let maskLayer1 = CAShapeLayer()
maskLayer1.path = path1.cgPath
maskLayer1.fillColor = UIColor.white.cgColor
maskLayer1.shadowColor = UIColor.darkGray.cgColor
maskLayer1.shadowPath = maskLayer1.path
maskLayer1.shadowOffset = CGSize(width: 0.0, height: 2.0)
maskLayer1.shadowOpacity = 0.6
maskLayer1.shadowRadius = 2
yourView.layer.insertSublayer(maskLayer1, at: 0)
Solved it by embedding innerView in another view. I applied the shadow to the new view and the radius to the innerView:
func addShadowTo(shadowView: UIView, andRadiusTo radiusView: UIView) {
let maskPath = UIBezierPath(roundedRect: radiusView.bounds, byRoundingCorners: UIRectCorner.BottomLeft.union(.BottomRight), cornerRadii: CGSize(width: 6, height: 6)).CGPath
shadowView.layer.shadowPath = maskPath
shadowView.layer.shadowColor = UIColor.blackColor().CGColor
shadowView.layer.shadowOffset = CGSizeMake(1, 2)
shadowView.layer.shadowOpacity = 0.2
shadowView.layer.shadowRadius = 2
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath
radiusView.layer.mask = maskLayer
}
If you are using Autolayout, then remove UIBezierPath. Try this code and custom one for yourself:
//This code custom a view with shadow and corner radius = 6
let shadowLayer: CALayer = shadowView.layer
shadowView.clipsToBounds = false
shadowLayer.shadowColor = 'your color'
shadowLayer.shadowOffset = CGSizeZero
shadowLayer.shadowOpacity = 1
shadowLayer.shadowRadius = 3
shadowLayer.shouldRasterize = true
let innerLayer: CALayer = innerView.layer
innerLayer.cornerRadius = 6
innerView.clipsToBounds = true
innerLayer.borderColor = 'your color'.CGColor
innerLayer.borderWidth = 1
The "innerView" is inside "shadowView" (on my xib file).

Resources