Swift 4 - imageview with two rounded corners in swift? - ios

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

Related

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

I am trying for corner radius to view which is placed inside UITableView. It doesn't work for me

I am trying to give corner radius to UIView which is placed in UITableViewCell. I need to display section like corner radius for every section so I am giving first cell to top right and top left corner radius and for the last cell to bottom right and bottom left corner radius. But it's not works for me.
Here is my code:
This is for the first cell (row) of UITableView
cell.viewMain.roundCorners(corners: [.topLeft, .topRight], radius: 10.0)
cell.layoutSubviews()
cell.layoutIfNeeded()
This is for the last cell (row) of UITableView
cell.viewMain.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10.0)
cell.layoutSubviews()
cell.layoutIfNeeded()
Extension which I am using:
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
}
}
I need output like this:
I had a similar problem a while back and what i was missing was that the table view is reusing the cells so we have to revert all the other cells to their default state.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! myCell
let isFirstCell = indexPath.row == 0
let isLastCell = indexPath.row == TotalRowsCount - 1
if isFirstCell && isLastCell {
cell.viewMain.topBottomRounded()
} else if isFirstCell {
cell.viewMain.topRounded()
} else if isLastCell {
cell.viewMain.bottomRounded()
} else {
// THIS IS THE KEY THING
cell.viewMain.defaultStateForBorders()
}
return cell
}
I have run your Code and its working fine except this thing.
where helping methods using your extension method are:
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
}
func topRounded() {
self.roundCorners(corners: [.topLeft, .topRight], radius: 10.0)
}
func bottomRounded() {
self.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10.0)
}
func topBottomRounded() {
self.roundCorners(corners: [.topLeft, .topRight,.bottomLeft, .bottomRight], radius: 10.0)
}
func defaultStateForBorders() {
self.roundCorners(corners: [], radius: 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.

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