I draw a dash border
let centerView = UIView()
centerView.frame = CGRect(x: 100, y: 100, width: 80, height: 50)
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.gray.cgColor
shapeLayer.lineDashPattern = [3, 2]
shapeLayer.lineWidth = 0.5
shapeLayer.path = UIBezierPath(
roundedRect: centerView.bounds,
cornerRadius: 22
).cgPath
view.addSubview(centerView)
centerView.layer.addSublayer(shapeLayer)
When I tap Debug View Hierarchy
Runtime issue:
A CAShapeLayer is used with a path that's a rect, a rounded-rect, or an ellipse. Instead, use an appropriately transformed plain CALayer with cornerRadius set.
How to fix it?
Use the layer's shadowPath instead of path
like this:
shapeLayer.shadowPath = UIBezierPath(
roundedRect: centerView.bounds,
cornerRadius: 22
).cgPath
Related
I am trying to add a dashed border on View which will always be on the view's frame not on it's bound .
My code :
func addDashedBorder() {
let color = UIColor.red.cgColor
shapeLayer = CAShapeLayer()
let frameSize = self.bounds.size
let shapeRect = CGRect(x:0 , y: 0, width: frameSize.width, height: frameSize.height)
shapeLayer.frame = shapeRect
shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2)
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 2
shapeLayer.lineJoin = CAShapeLayerLineJoin.round
shapeLayer.lineDashPattern = [6,3]
shapeLayer.path = UIBezierPath(roundedRect: self.frame, cornerRadius: 5).cgPath
self.layer.addSublayer(shapeLayer)
}
Result
I don't want to rotate the Border on View if we rotate the view .
it should indicate how much space its is taking on view .
Expectation
You need to take two view i.e inner and outer view. Inner view (rotation view) should be in the subview of outer view. The frame must be same for both views. Use the following line of code -
#IBOutlet weak var viewOuter: UIView! //static outer view
#IBOutlet weak var viewInner: UIView! // View that will be use for rotation
func addDashedBorder() {
let color = UIColor.red.cgColor
let shapeLayer = CAShapeLayer()
let frameSize = viewInner.bounds.size
let shapeRect = CGRect(x:0 , y: 0, width: frameSize.width, height: frameSize.height)
shapeLayer.frame = shapeRect
shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height/2)
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 2
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineDashPattern = [6,3]
shapeLayer.path = UIBezierPath(roundedRect: viewInner.frame, cornerRadius: 5).cgPath
self.viewOuter.layer.addSublayer(shapeLayer)
}
Using this example I am trying to add a dashed border to my UITableView.
Trying to draw dashed border for UITableViewCell
But it does not work. It shows nothing.
func addDashedBottomBorder(to cell: UITableViewCell) {
let color = UIColor.black.cgColor
let shapeLayer:CAShapeLayer = CAShapeLayer()
let frameSize = cell.frame.size
let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: 0)
shapeLayer.bounds = shapeRect
shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height)
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 2.0
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineDashPattern = [9,6]
shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: shapeRect.height, width: shapeRect.width, height: 0), cornerRadius: 0).cgPath
cell.layer.addSublayer(shapeLayer)
}
I am using this method in cellForRowAt but it shows me nothing and in viewDidLoad, table.separatorStyle = .none.
From the below 2 lines of your code:
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: shapeRect.height, width: shapeRect.width, height: 0), cornerRadius: 0).cgPath
kCALineJoinRound is making upper and lower dash lines but they are overlapping due to the height of UIBezierPath is 0. So, Updated your code as:
shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: shapeRect.height, width: shapeRect.width, height: 1), cornerRadius: 0).cgPath
It will hide the lower line and you will get the desired result.
Best Solution:
Rather than hiding lower dash line, you can correct it by providing just lineDashPhase to your CAShapeLayer, as:
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineDashPhase = 3.0 // Add "lineDashPhase" property to CAShapeLayer
shapeLayer.lineDashPattern = [9,6]
shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: shapeRect.height, width: shapeRect.width, height: 0), cornerRadius: 0).cgPath
Received line is:
I've make a path in order to mask my view:
let path = // create magic path (uiview bounds + 2 arcs)
let mask = CAShapeLayer()
mask.path = path.cgPath
view.layer.masksToBounds = false
view.layer.mask = mask
Up to here all ok.
Now I would like to add a shadow that follows path, is it possibile?
I try in several way, the last one is:
mask.shadowPath = path.cgPath
mask.shadowColor = UIColor.red.cgColor
mask.shadowOffset = CGSize(width: 10, height: 2.0)
mask.shadowOpacity = 0.5
But this produce a partial shadow and with color of the original view..
With debug view hierarchy:
Any advice?
Final result should be similar to this, but with shadow that "follows" arcs on path.
When you add a mask to a layer, it clips anything outside that mask - including the shadow. To achieve this you'll need to add a "shadow" view below your masked view, that has the same path as the mask.
Or add a shadow layer to the masked view's superview.
let view = UIView(frame: CGRect(x: 50, y: 70, width: 100, height: 60))
view.backgroundColor = .cyan
let mask = CAShapeLayer()
mask.path = UIBezierPath(roundedRect: view.bounds, cornerRadius: 10).cgPath
view.layer.mask = mask
let shadowLayer = CAShapeLayer()
shadowLayer.frame = view.frame
shadowLayer.path = UIBezierPath(roundedRect: view.bounds, cornerRadius: 10).cgPath
shadowLayer.shadowOpacity = 0.5
shadowLayer.shadowRadius = 5
shadowLayer.masksToBounds = false
shadowLayer.shadowOffset = .zero
let container = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
container.backgroundColor = .white
container.layer.addSublayer(shadowLayer)
container.addSubview(view)
If you're going to be using this elsewhere, you could create a ShadowMaskedView that contains the shadow layer, and the masked view - maybe with a path property.
You can try this extension:
extension UIView {
func dropShadow() {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = 0.5
self.layer.shadowOffset = CGSize(width: -1, height: 1)
self.layer.shadowRadius = 1
self.layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
self.layer.shouldRasterize = true
}
}
I'm trying to draw an empty circle with a stroke color with a shadow.
let bezierPath = UIBezierPath(ovalIn: CGRect(x: 80, y: 200, width: 100, height: 100))
let shapeLayer = CAShapeLayer()
shapeLayer.path = bezierPath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.white.cgColor
shapeLayer.lineWidth = 3
shapeLayer.shadowPath = bezierPath.cgPath
shapeLayer.shadowColor = UIColor.black.cgColor
shapeLayer.shadowOffset = CGSize(width: 0, height: 0)
shapeLayer.shadowOpacity = 1
containerView.layer.addSublayer(shapeLayer)
But shadow is filling the entire circle. How to remove it and keep the outer shadow ?
Just omit setting shapeLayer.shadowPath and you will get something like this (the layer's standard shadow, which is basically the opaque parts of the layer):
Hello Guys i have been trying to Draw the Dotted line below UILabel using this code
extension UIView{
func addDashedBorder() {
self.layoutIfNeeded()
let color = UIColor.lightGrayColor().CGColor
let shapeLayer:CAShapeLayer = CAShapeLayer()
let frameSize = self.frame.size
let shapeRect = CGRect(x: 0, y: 0, width: frameSize.width, height: 0)
shapeLayer.bounds = shapeRect
shapeLayer.position = CGPoint(x: frameSize.width/2, y: frameSize.height)
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = color
shapeLayer.lineWidth = 0.50
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineDashPattern = [3,2]
shapeLayer.path = UIBezierPath(roundedRect: CGRectMake(0, shapeRect.height, shapeRect.width, 0), cornerRadius: 0).CGPath
self.layer.addSublayer(shapeLayer)
}
}
So here i have been trying to create the extension so i can utilize it to every where in my code. but this doesn't give me the perfect result some time.
sometimes this code failed just check the Gender and Birth date in both the label i have used the same code but not getting the expected result, Any suggestion ?