CornerRadius don't set - ios

I'm trying to round the corners on the UIView in bottom left and bottom right.
extension UIView {
func roundBottom(raduis: CGFloat){
let maskPath1 = UIBezierPath(roundedRect: bounds,
byRoundingCorners: [.BottomRight, .BottomLeft],
cornerRadii: CGSize(width: raduis, height: raduis))
let maskLayer1 = CAShapeLayer()
maskLayer1.frame = bounds
maskLayer1.path = maskPath1.CGPath
layer.mask = maskLayer1
}
}
And call cell.bottomCorner.roundBottom(8)
But I get it:
iPhone 5:
iPhone 6s:
iPhone 6s Plus:

You have to update the mask everytime the view changes its size, therefore ideally you should change it whenever UIView.layoutSubviews is called:
override func layoutSubviews() {
super.layoutSubviews();
// update mask
}
It's not ideal to do it in an extension helper method. You should create a specific class to handle the size change.

Related

Error Specific RoundCorners on Old Devices?

I added round corners function extension inside UIView
it works perfectly on a new device like iPhone XR but the old device with 16:9 ratio like iPhone 8,iPhone 8 plus it corners in just the left
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
}
}
When I implement the function. inside the UIViewController, I call the function inside viewDidLayoutSubviews
//ViewController
override func viewDidLayoutSubviews() {
exampleView.roundCorners([.topRight,.topLeft], radius: 20)
}
but when I implement in class with another type I couldn't find a solution,
I want a method to force take the corner always.
If you want a view to always have cornerradius you can use following snippet:
#IBDesignable extension UIView{
#IBInspectable var cornerRadius : CGFloat{
get{
return self.layer.cornerRadius
}set{
layer.cornerRadius = newValue
clipsToBounds = true
}
}
}
You can set the radius in the InterfaceBuilder or in code.

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)
}

Bezierpath button width issue

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
}
I am using this function to give corner radius from particular side for UIButton. I am calling this function into UITableViewCell but I am having issue like I gave constraint to button like its width is changing as per device width change for exa if device is iPhone 5 then its width is 159.5 acoordingly half of screen width. but it is not changing and button is cutting from its width.
I am calling this function in TableviewCell
override func layoutSubviews() {
super.layoutSubviews()
self.btnWithdraw.roundCorners([.bottomRight], radius: 4.0)
self.btnAddFund.roundCorners([.bottomLeft], radius: 4.0)
}
But here issue is like It is taking original frame as per given in storyboard viewcontroller and button is not taking width as per constraints.
Any help would appreciated.
Thank you
Perhaps the problem is that you are assuming that layoutSubviews will be called on the cell under all circumstances where the button is being laid out afresh. That might not be true.
To avoid that assumption, implement your entire masking in the button itself, along these lines:
class MyButton : UIButton {
var whatCorners : UIRectCorner = [.bottomRight]
var whatRadius : CGFloat = 4.0
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
}
override func layoutSubviews() {
super.layoutSubviews()
self.roundCorners(self.whatCorners, radius: self.whatRadius)
}
}
That way, you can give each button the desired values for whatCorners and whatRadius and the button will round itself.

rounding corners of UIbutton disturbing its width

I have three buttons in which I want to round:
Top corners of first button
Bottom corners of second button
All four corners of third button
I achieved this by the following code:
button1.roundedButton1()
button2.roundedButton2()
button3.layer.cornerRadius = 5
extension UIButton {
func roundedButton1(){
let maskPAth1 = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft , .topRight],
cornerRadii:CGSize(width:5.0, height:5.0))
let maskLayer1 = CAShapeLayer()
// maskLayer1.frame = self.bounds
maskLayer1.path = maskPAth1.cgPath
self.layer.mask = maskLayer1
}
func roundedButton2(){
let maskPAth1 = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.bottomLeft , .bottomRight],
cornerRadii:CGSize(width:5.0, height:5.0))
let maskLayer1 = CAShapeLayer()
maskLayer1.frame = self.bounds
maskLayer1.path = maskPAth1.cgPath
self.layer.mask = maskLayer1
}
}
But the width of my 1st and 2nd button is getting disturbed.
If I use button2.layer.cornerRadius = 5 then the width becomes alright. I have searched which code it altering its width but didn't find anything appropriate. And this is the only working solution i found for UIButton.Can anyone tell me why the width of button is changing and how to fix it?
The constraints of button are as follows:
Instead of using UIButton you can achieve this result by using UIView & UITapGestureRecognizer
add this extension
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
}
}
then create a custom view class
class CustomView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
self.roundCorners([.topRight, .topLeft], radius: 5) // you can use .topRight , .topLeft , .bottomRight, .bottomLeft
}
}
then use the class on your view
Hope this will help you

Smooth only top angles and imageview in Swift

I'm trying to round only the top top corners (TopLeft and TopRight) of a view and imageview. With the code below I was able to round up only the left corner (although there is also specified TopRight). Maybe he doesn't see the constraint placed on the storyboard.
How do I fix?
Thank you.
let rectShape = CAShapeLayer()
rectShape.bounds = self.CopertinaImage1.frame
rectShape.position = self.CopertinaImage1.center
rectShape.path = UIBezierPath(roundedRect: self.CopertinaImage1.bounds, byRoundingCorners: [.TopRight, .TopLeft], cornerRadii: CGSize(width: 10, height: 10)).CGPath
self.CopertinaImage1.layer.backgroundColor = UIColor.greenColor().CGColor
self.CopertinaImage1.layer.mask = rectShape
The right corner is always the same:
Edit:
I've tried placing the following code in viewDidLayoutSubviews:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let rectShape = CAShapeLayer()
rectShape.bounds = self.CopertinaImage1.frame
rectShape.position = self.CopertinaImage1.center
rectShape.path = UIBezierPath(roundedRect: self.CopertinaImage1.bounds, byRoundingCorners: [.TopRight, .TopLeft], cornerRadii: CGSize(width: 10, height: 10)).CGPath
self.CopertinaImage1.layer.backgroundColor = UIColor.greenColor().CGColor
self.CopertinaImage1.layer.mask = rectShape
}
But it didn't work.
I've tried the code you've posted. For whatever reason when I enter your constraints and recreate your view hierarch, the auto layout engine does not call viewDidLayoutSubviews after it does it's second pass. I could force it to but calling self.view.layoutIfNeeded() from viewWillAppear. For example:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let rectShape = CAShapeLayer()
rectShape.frame = self.imageView.bounds
rectShape.path = UIBezierPath(roundedRect: self.imageView.bounds, byRoundingCorners: [.TopRight, .TopLeft], cornerRadii: CGSize(width: 10, height: 10)).CGPath
self.imageView.layer.backgroundColor = UIColor.greenColor().CGColor
self.imageView.layer.mask = rectShape
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.view.layoutIfNeeded()
}
Results in:
With both corners rounded.
I would say a better, more elegant solution that avoids this auto layout glitch is to just set the corner radius of the image view container, as it seems like that what you're doing anyways. For example:
override func viewDidLoad() {
super.viewDidLoad()
self.imageView.clipsToBounds = true
self.imageContainerView.layer.cornerRadius = 10.0
self.imageContainerView.layer.masksToBounds = true
}
You can also do this from viewDidLoad because it doesn't depend on any of your views' frames being set.
I just tried your code in a playground. Worked fine for me. Maybe I am misunderstanding the problem.

Resources