UIBezierPath - byRoundingCorners - Rect - ios

I have a very easy view controller..
import UIKit
class ViewController: UIViewController {
let f = TstKocka(frame: CGRectMake(100,100, 150, 150))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(f)
}
}
And I have a UIView class:
class TstKocka: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(rect: CGRect) {
var path = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSize(width: 2.0, height: 2.0))
path.lineWidth = 1.0
path.stroke()
}
}
And I'm trying to create a rounded rect but I don't know how to do. I've read lot of tutorials but none of them worked for me.Please help me.

since you are not providing a fill color i guess your rect shall have a clear color. to make that work change your initwithframe to the following:
override init(frame: CGRect) {
super.init(frame: frame)
opaque = false
}
then increase cornerradii value (to 20.0, 20.0 for example) to see that it works! :)
EDIT
filling is actually as simple as stroking:
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSize(width: 20.0, height: 20.0))
path.lineWidth = 1.0
UIColor.blueColor().setFill() // or whatever fill color you like
path.fill()
UIColor.redColor().setStroke()
path.stroke()

If you are trying to create a rounded rect view that clips the content, you should use layer masks or the simple -cornerRadius property on the views layer, setting also the -borderWidth.
If you just want a view background rounded rect, before stroking you should set the stroke color.
I don't know swift but in objC could be something like this
- (void) drawRect:(CGRect) rect {
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5.0];
[[UIColor redColor] setStroke];
[bezierPath stroke];
}
In Swift probably:
override func drawRect(rect: CGRect) {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSize(width: 2.0, height: 2.0))
UIColor.redColor().setStroke()
path.lineWidth = 1.0
path.stroke()
}

Related

How to add corner radius for UIView

I have to set some corner radius of UIView and I set it by this code:
#IBDesignable
class MyUIviewCorner: UIView {
override func layoutSubviews() { setup() }
func setup() {
let r = self.bounds.size.height / 2
let path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: r, height: r))
let mask = CAShapeLayer()
mask.backgroundColor = UIColor.clear.cgColor
mask.path = path.cgPath
layer.borderWidth = 1.5
layer.borderColor = UIColor.red.cgColor
self.layer.mask = mask
}
}
But I get this result:
I don't understand why is there white spaces on the top corners?
If I set bottom corner radius I get this:
You shouldn't use a mask for this, you can simply use the layer.maskedCorners property.
layer.cornerRadius = r
layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
You can kind of see why if you increase the border width:
There seems to still be a filled rectangle "on top of" the rounded rectangle drawn by the created layer, covering up the rounded corner.
You can achieve what you want by just drawing with UIBezierPaths:
override func draw(_ rect: CGRect) {
let r = self.bounds.size.height / 2
let path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: r, height: r))
path.lineWidth = 1.5
UIColor.red.setStroke()
path.stroke()
}

round bottomRight with byRoundingCorners not work

I'm trying to make round corner for topLeft and rightBottom, the top round work well but leftBottom still rectangle,
I searched a lot I think it's overlap issue but don't know how to fix it, please any help?
P.S. it's work well just in IPhone Xs Max
import UIKit
#IBDesignable
class CustomView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setRadius()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setRadius()
}
override func prepareForInterfaceBuilder() {
setRadius()
}
func setRadius()
{
let cornerRadius = 18.0
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let maskLayer = CAShapeLayer()
self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
maskLayer.frame = self.bounds
maskLayer.path = path.cgPath
self.layer.mask = maskLayer
}
}
Try this
let your_Frame = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))//define your frame size you want
your_Frame.layer.cornerRadius = 25//deine the radius you want
your_Frame.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMaxYCorner]
view.addSubview(your_Frame)

UIBezierPath not rendering properly

I have a tablviewcell which has uiview in it.
Based on some logic I change the background color and make the left and right corner rounded.
I make these view corner round from cellForRowat indexPath function.
Here is my extension.
extension UIView {
func roundCorners(corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
and how I use it
cell?.myCustomView.roundCorners(corners: [.bottomRight,.bottomLeft], radius: 10.0)
Its working fine when width of iphones is 375,
but it fails to update for device with width greater than 375.
And after scrolling the tableview, it again stretches back correctly to the desired width.
How to solve this problem ?
You want to update the path when the view changes size. In cellForRowAt the cell has not yet been fully laid-out by auto-layout.
So...
Create a UIView subclass for your "rounded corners" view (simple example):
class RoundedCornersView: UIView {
var corners: UIRectCorner = UIRectCorner()
var radius: CGFloat = 0.0
override func layoutSubviews() {
super.layoutSubviews()
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
Now, anytime the view changes size - such as on first use or device rotation, for example - the view will automatically update the path.
Here is how you would use it in a table cell. In Storyboard, set the class of the "background view" to RoundedCornersView
class RoundedCornersView: UIView {
var corners: UIRectCorner = UIRectCorner()
var radius: CGFloat = 0.0
override func layoutSubviews() {
super.layoutSubviews()
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
class MyTestCell: UITableViewCell {
#IBOutlet var myCustomView: RoundedCornersView!
}
Then, in cellForRowAt:
let cell = tableView.dequeueReusableCell(withIdentifier: "MyTestCell", for: indexPath) as! MyTestCell
if shouldBeRounded {
cell.myCustomView.corners = [.bottomRight, .bottomLeft]
cell.myCustomView.radius = 10.0
cell.myCustomView.backgroundColor = .green
} else {
cell.myCustomView.corners = []
cell.myCustomView.radius = 0.0
cell.myCustomView.backgroundColor = .white
}
return cell
Use this:
override func draw(_ rect: CGRect) {
super.draw(rect)
selectedView.roundCorners(corners: [.topLeft, .topRight], radius: 12.0)
}

UITableViewCell TopLeft and BottomLeft Corners not working

I'm new to iOS development and trying to create a custom UITableViewCell that has a background which top-left and bottom-left corners I want to round, but it only works for the top-left corner.
Here is my code (Swift 3):
override func awakeFromNib() {
super.awakeFromNib()
let bgViewMask = CAShapeLayer()
let bgViewPath = UIBezierPath(
roundedRect: bgView.bounds,
byRoundingCorners: [.topLeft, .bottomLeft],
cornerRadii: CGSize(width: 8, height: 8)
)
bgViewMask.frame = bgView.bounds
bgViewMask.path = bgViewPath.cgPath
bgView.layer.mask = bgViewMask
}
I also tried this in layoutSubviews()
override func layoutSubviews() {
super.layoutSubviews()
//code here
}
but it didn't work as well.
If I use bgView.layer.cornerRadius = 8 it works for all corners.
Am I doing anything wrong?
You can try this:
import UIKit
class CustomImageView: UIImageView {
override public func layoutSubviews() {
super.layoutSubviews()
self.roundUpCorners([.topLeft, .bottomLeft], radius: 8)
}
}
extension UIView {
func roundUpCorners(_ 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
}
}

Round bottom line of an image view

I want only the bottom border of my imageView to be rounded. How do I do that programmatically?
Thanks for your help!
You can do this by sub-classing UIImageView:
import UIKit
class CustomImageView: UIImageView {
override public func layoutSubviews() {
super.layoutSubviews()
self.roundUpCorners([.bottomLeft, .bottomRight], radius: 30)
}
}
extension UIView {
func roundUpCorners(_ 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
}
}
The result will be something like this:

Resources