Round Corners of resizable view - ios

Ive been using the code shown below to round selected corners of views, however am now having trouble achieving this on a resizable view as the layer? isn't updated each time the view is resized.
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
}
}
titleLabelView.roundCorners(corners: [.topLeft, .topRight], radius: 10)
There is a similar question here but its quite old and all done in objC.
Is there a way of rounding selected corners in swift for resizable views?
----- EDIT -----
So essentially what i have is a text table that i have set to resize based on the size of the text.
In most cases i can just use:
myTextLabel.layer.cornerRadius = 10
However this does all 4 corners. So if i want to round just the top 2 then i need to use the extension above. Now because i am using scrollViewDidEndDecelerating to set the content for the label (i need to get the indexPath for the cell at the centre of the collectionView so i can set the text label)
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
GeneralFunctions.getIndexOfCell(sender: self) { (index) in
self.titleLabel.text = self.partArray[index].title
self.titleLabel.roundCorners(corners: [.topLeft, .topRight], radius: 10)
self.descriptionLabel.text = self.partArray[index].description
self.descriptionLabel.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
self.backgroundLabelView.layer.cornerRadius = 16
self.backgroundLabelView.layoutIfNeeded()
self.backgroundLabelView.layoutSubviews()
}
}
Using viewDidLayoutSubViews doesn't work in this case as there is a lag between accelerating ending and the layout. I have tried using the same code(without the check for the centre index) inside viewDidLayoutSubViews but the result is the same.
And The label does resize correctly when i don't use any of the corner rounding.

I had similar problem, I've solved it by using this function like
DispatchQueue.main.async(execute: {
self.roundCorners(.allCorners, radius: 6, borderColor: nil, borderWidth: nil)
})
I am using this function a lot for UITableViewCell, and my whole code looks like
private var didLayoutSubview = false {
didSet {
DispatchQueue.main.async(execute: {
self.roundCorners(.allCorners, radius: 6, borderColor: nil, borderWidth: nil)
})
}
}
override func layoutSubviews() {
if !self.didLayoutSubview {
self.didLayoutSubview = true
}
super.layoutSubviews()
}
So basically, calling this function in main thread helped, and I am calling it inside layoutSubivews because I think it is the place.
My function
func roundCorners(_ corners: UIRectCorner, radius: CGFloat, borderColor: UIColor?, borderWidth: CGFloat?) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.frame = self.bounds
mask.path = path.cgPath
self.layer.mask = mask
if borderWidth != nil {
addBorder(mask, borderWidth: borderWidth!, borderColor: borderColor!)
}
}

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

Swift 4 - imageview with two rounded corners in swift?

I have a UIImageView inside of a UICollectionView Cell and I wanna make it' s top corners rounded. I couldn' t solve on my on, any help is appreciated.
You can see cell has 10px corner radius and I want same effect to be applied on image too.
You can try UIRectCorner Document here
here my custom class AGRoundCornersView
extension UIImageView {
public func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let maskPath = UIBezierPath(roundedRect: bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let shape = CAShapeLayer()
shape.path = maskPath.cgPath
layer.mask = shape
}
}
code :
1. Call When View is resized.
uiimage.roundCorners([.topLeft, .topRight], radius: 10)
2. Create custom class
class CustomImageView: UIImageView {
override func layoutSubviews() {
super.layoutSubviews()
self.roundCorners([.topLeft, .topRight], radius: 10)
}
}
Swift 5
In your collectionview cell, put the below two lines of code & you are good to go. No need to write any extension:
cell._imageView.layer.cornerRadius = 10
cell._imageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
Here corner radius will apply TopLeft & TopRight corners & rest of corners will remain same.
If you want to apply the corner radius in BottomLeft & BottomRight corners, then maskedCorners should look like the below:
cell._imageView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
Hope it helps.
Try this in your UICollectionViewCell
override func awakeFromNib() {
super.awakeFromNib()
DispatchQueue.main.async {
self.image.roundCorners([.topRight,.topLeft], radius: 8)
self.image.layer.masksToBounds = true
}
}
Thanks to AshvinGudaliya and Sujewan
Following code worked for my collection cell's ImageView Top Left-Right corners
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:TUGBucketCell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! TUGBucketCell
//Rounded corner ImageView
DispatchQueue.main.async {
cell.imgVw.roundCorners([.topLeft, .topRight], radius: 10)
cell.imgVw.layer.masksToBounds = true
}
return cell
}
and the extension is
extension UIImageView {
public func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let maskPath = UIBezierPath(roundedRect: bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let shape = CAShapeLayer()
shape.path = maskPath.cgPath
layer.mask = shape
}
}

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.

Swift3 round two corners of UIView

I know this question already asked so many times and their solutions also available but nothing works for me.
I am using Swift3 and I want to round any two sides of UIView for this purpose I found the following solution
Create a rectangle with just two rounded corners in swift?
and following is my code snippet of the above solution
extension UIView {
/**
Rounds the given set of corners to the specified radius
- parameter corners: Corners to round
- parameter radius: Radius to round to
*/
func round(corners: UIRectCorner, radius: CGFloat) -> Void {
layer.addSublayer(_round(corners: corners, radius: radius))
}
/**
Rounds the given set of corners to the specified radius with a border
- parameter corners: Corners to round
- parameter radius: Radius to round to
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let mask = _round(corners: corners, radius: radius)
addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}
/**
Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border
- parameter diameter: The view's diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
layer.masksToBounds = true
layer.cornerRadius = diameter / 2
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor;
}
}
private extension UIView {
func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
return mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
layer.addSublayer(borderLayer)
}
}
This is the result I got. I don't know what I am doing wrong.
Can anyone please solve this?
Code tested and worked in Swift 3.
Use below extension to create roundCorners.
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
}
}
Usage: in viewDidLoad
yourViewName.roundCorners(corners: [.topRight, .bottomLeft], radius: 10)
Output:
First of all you will need to Make IBOutlet for that Textfield or Button which you
need to Be Rounded Corner
Go to The ViewDidLoad() Method
Write the name of IBOutLet
Example Code mybutton.layer.cornerRadius=10
Here is the Solution to Your Problem

Resources