UIView not shows round - ios

For making a circular UIView I am using the cornerRadius property.
I have a UIView with dimension 79*158.
redView.layer.cornerRadius = redView.frame.size.height/2
redView.layer.masksToBounds = true
It shows elipse instead of circle:
Any workaround or does it only work with square type (eg. UIView(100*100))?
I am ok if it resizes dynamically.

use this...
func makeCircle (view: UIView) {
view.clipsToBounds = true
let height = view.frame.size.height
let width = view.frame.size.width
let newHeight = min(height, width) // use "max" if you want big circle
var rectFrame = view.frame
rectFrame.size.height = newHeight
rectFrame.size.width = newHeight
view.frame = rectFrame
view.layer.cornerRadius = newHeight/2
}
use like this:
#IBOutlet var rectView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
makeCircle(view: rectView)
}

You have a UIView with dimension 79*158.So that is wrong. You should have exactly same height and width for rounding exact a view to circle shape.
E.g.
redView.frame.size.height = 79.0
redView.frame.size.width = 79.0
or
redView.frame.size.height = 158.0
redView.frame.size.width = 158.0
And apply corner radius like:
redView.clipsToBounds = true
redView.layer.cornerRadius = redView.frame.size.height / 2.0
Result:
Note: Check your constrains also If you are using Auto Layout. Be sure view frame doesn't change.

If you are using constraints then changing the frame/bounds of the view is not a good idea. Instead you should do the following.
If the view is contained in a UIViewController then set the cornerRadius in viewDidLayoutSubviews method
And if the view is itself a subclass of UIView the set the cornerRadius in layoutSubviews method

Only Squire view make a perfect circle. For example, if your view size is (10*10),(50*50),(100*100), etc. then your view becomes perfect squire else not.

Using IBDesignable, you can display without project run in storyboard ox .XIB #simple way
Step 1. Subclass UIView:
#IBDesignable class RoundedCornerView: UIView {
#IBInspectable var borderWidth:CGFloat = 2 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor:UIColor = UIColor.orangeGradientLight {
didSet {
layer.borderColor = borderColor.cgColor
}
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = frame.height/2
layer.masksToBounds = true
layer.borderColor = borderColor.cgColor
layer.borderWidth = borderWidth
}
}
Step 2. Set custom class in identity inspector:

can't.
Try resize UIView to square: 79*79 OR 158*158
And set:
redView.layer.cornerRadius = redView.frame.size.height/2

Related

How to use UIView in UIViewController ios

I make UIView like this. but I want to use this in UIViewController
What should I do?
import UIKit
class CardView: UIView {
#IBInspectable var cornerRadius: CGFloat = 2
#IBInspectable var shadowOffsetWidth: Int = 0
#IBInspectable var shadowOffsetHeight: Int = 3
#IBInspectable var shadowColor: UIColor? = UIColor.black
#IBInspectable var shadowOpacity: Float = 0.5
override func layoutSubviews() {
layer.cornerRadius = cornerRadius
let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
layer.masksToBounds = false
layer.shadowColor = shadowColor?.cgColor
layer.shadowOffset = CGSize(width: shadowOffsetWidth, height: shadowOffsetHeight);
layer.shadowOpacity = shadowOpacity
layer.shadowPath = shadowPath.cgPath
}
}
If you want to add it in your viewController you have several options:
Add it directly in storyboard (best option):
drag a view in viewController via inspector/object library on the bottom right side in xCode
UIView object screenshot
add constraints, then tap on the view in
Constraints screenshot
and pick your custom class in identity inspector/custom class field
You can also use a view loaded from xib
Google different way to load from xib.
You can add it in code. It's a little bit harder:
Create a lazy property:
lazy var cardView: CardView = {
let cardView = CardView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
cardView.backgroundColor = .gray
cardView.layer.cornerRadius = 16.0
return cardView
}()
Add custom view in viewDidLoad for example:
override func viewDidLoad() {
super.viewDidLoad()
/* Adding subview to the VC */
view.addSubview(cardView)
}
Then add constraints. You can center it vertically/horizontally and then set custom height/width. It depends on what you want...
Check this out:
Swift | Adding constraints programmatically
I advise you to read Apple's documentation rather then just copy pasting code.
Should definitely read "documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html" if you still haven't.
Add a new uiview to your storyboard or xib file and set its class as CardView as shown

Creating a shadow for a UIImageView that has rounded corners?

I am trying to create an ImageView that has rounded corners and a shadow to give it some depth. I was able to create a shadow for the UIImageView, but whenever I added the code to also make it have rounded corners, it only had rounded corners with no shadow. I have an IBOutlet named myImage, and it is inside of the viewDidLoad function. Does anybody have any ideas on how to make it work? What am I doing wrong?
override func viewDidLoad() {
super.ViewDidLoad()
myImage.layer.shadowColor = UIColor.black.cgColor
myImage.layer.shadowOpacity = 1
myImage.layer.shadowOffset = CGSize.zero
myImage.layer.shadowRadius = 10
myImage.layer.shadowPath = UIBezierPath(rect: myImage.bounds).cgPath
myImage.layer.shouldRasterize = false
myImage.layer.cornerRadius = 10
myImage.clipsToBounds = true
}
If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. In order to resolve this, you can create two views. The container view should have the shadow, and its subview should have the rounded corners.
The container view has clipsToBounds set to false, and has the shadow properties applied. If you want the shadow to be rounded as well, use the UIBezierPath constructor that takes in a roundedRect and cornerRadius.
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath
Next, set the image view (or any other type of UIView) to be the same size of the container view, set clipsToBounds to true, and give it a cornerRadius.
let myImage = UIImageView(frame: outerView.bounds)
myImage.clipsToBounds = true
myImage.layer.cornerRadius = 10
Finally, remember to make the image view a subview of the container view.
outerView.addSubview(myImage)
The result should look something like this:
Swift 5:
You can use the below extension:
extension UIImageView {
func applyshadowWithCorner(containerView : UIView, cornerRadious : CGFloat){
containerView.clipsToBounds = false
containerView.layer.shadowColor = UIColor.black.cgColor
containerView.layer.shadowOpacity = 1
containerView.layer.shadowOffset = CGSize.zero
containerView.layer.shadowRadius = 10
containerView.layer.cornerRadius = cornerRadious
containerView.layer.shadowPath = UIBezierPath(roundedRect: containerView.bounds, cornerRadius: cornerRadious).cgPath
self.clipsToBounds = true
self.layer.cornerRadius = cornerRadious
}
}
How to use:
Drag a UIView on the storyboard
Drag an ImageView inside that UIView
Storyboard should look like this:
Create IBOutlet for both Views, call extension on your ImageView, and pass above created UIView as an argument.
Here is the output :
Finally here is how to
Properly have an image view, with rounded corners AND shadows.
It's this simple:
First some bringup code ..
class ShadowRoundedImageView: UIView {
override init(frame: CGRect) {
super.init(frame: frame); common() }
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder); common() }
private func common() {
backgroundColor = .clear
clipsToBounds = false
self.layer.addSublayer(shadowLayer)
self.layer.addSublayer(imageLayer) // (in that order)
}
#IBInspectable var image: UIImage? = nil {
didSet {
imageLayer.contents = image?.cgImage
shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
}
}
and then the layers ...
var imageLayer: CALayer = CALayer()
var shadowLayer: CALayer = CALayer()
var shape: UIBezierPath {
return UIBezierPath(roundedRect: bounds, cornerRadius:50)
}
var shapeAsPath: CGPath {
return shape.cgPath
}
var shapeAsMask: CAShapeLayer {
let s = CAShapeLayer()
s.path = shapeAsPath
return s
}
override func layoutSubviews() {
super.layoutSubviews()
imageLayer.frame = bounds
imageLayer.contentsGravity = .resizeAspectFill // (as preferred)
imageLayer.mask = shapeAsMask
shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
shadowLayer.shadowOpacity = 0.80 // etc ...
}
}
Here is the
Explanation
UIImageView is useless, you use a UIView
You need two layers, one for the shadow and one for the image
To round an image layer you use a mask
To round a shadow layer you use a path
For the shadow qualities, obviously add code as you see fit
shadowLayer.shadowOffset = CGSize(width: 0, height: 20)
shadowLayer.shadowColor = UIColor.purple.cgColor
shadowLayer.shadowRadius = 5
shadowLayer.shadowOpacity = 0.80
For the actual shape (the bez path) make it any shape you wish.
(For example this tip https://stackoverflow.com/a/41553784/294884 shows how to make only one or two corners rounded.)
Summary:
• Use two layers on a UIView
Make your bezier and ...
• Use a mask on the image layer
• Use a path on the shadow layer
Here is a another solution (tested code) in swift 2.0
If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. So, you can add same size UIView in storyboard behind imageview and we can give shadow to that view
SWIFT 2.0
outerView.layer.cornerRadius = 20.0
outerView.layer.shadowColor = UIColor.blackColor().CGColor
outerView.layer.shadowOffset = CGSizeMake(0, 2)
outerView.layer.shadowOpacity = 1
outerView.backgroundColor = UIColor.whiteColor()
You can use a simple class I have created to add image with rounded corners and shadow directly from Storyboard
You can find the class here

How to keep a round imageView round using auto layout?

How do I turn a rectangular image view into a circular image view that can hold shape in auto layout without setting width and height restraints? Thereby allowing the imageView to define it’s size, and size bigger and smaller relative to objects around it with leading, trailing, top, and bottom constraints.
I asked a similar question the other day, but I think this might be posed in a more concise way. Thanks so much!
EDIT
Ok, I started over to make this as simple as possible. I have a view named "Cell" and a UIImageView named "dog" within the cell, and that's it. I don't have "unable to simultaneously satisfy constraints" in the console anymore, just two simple views using auto layout. I'm still trying to use this code to round the UIImageView:
profileImageView.layer.cornerRadius = profileImageView.frame.size.width / 2
profileImageView.clipsToBounds = true
Here is the cell constraint setup:
Here is the profile pic constraint setup:
Here is the result without the code, no rounding, but nice and square:
Here is the result with the code to round:
This makes no sense to me, because without the rounding code the image is square, and with the code it's diamond shaped. If it's square shouldn't it be a circle with no issues?
EDIT 2
Here's what happens when I remove the bottom constraint and add a multiplier of .637 for equal height to superview.
Unfortunately you cannot do this using cornerRadius and autolayout — the CGLayer is not affected by autolayout, so any change in the size of the view will not change the radius which has been set once causing, as you have noticed, the circle to lose its shape.
You can create a custom subclass of UIImageView and override layoutSubviews in order to set the cornerRadius each time the bounds of the imageview change.
EDIT
An example might look something like this:
class Foo: UIImageView {
override func layoutSubviews() {
super.layoutSubviews()
let radius: CGFloat = self.bounds.size.width / 2.0
self.layer.cornerRadius = radius
}
}
And obviously you would have to constrain the Foobar instance's width to be the same as the height (to maintain a circle). You would probably also want to set the Foobar instance's contentMode to UIViewContentMode.ScaleAspectFill so that it knows how to draw the image (this means that the image is likely to be cropped).
Setting radius in viewWillLayoutSubviews will solve the problem
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
profileImageView.layer.cornerRadius = profileImageView.frame.height / 2.0
}
create new interface in your .h file like
#interface CornerClip : UIImageView
#end
and implementation in .m file like
#implementation cornerClip
-(void)layoutSubviews
{
[super layoutSubviews];
CGFloat radius = self.bounds.size.width / 2.0;
self.layer.cornerRadius = radius;
}
#end
now just give class as "CornerClip" to your imageview.
100% working... Enjoy
First of all, I should mention that u can get a circle shape for your UIView/UIImageView only if the width and height will be equal. It's important to understand. In all other cases (when width != height), you won't get a circle shape because the initial shape of your UI instance was a rectangle.
OK, with this so UIKit SDK provides for developers a mechanism to manipulate the UIview's layer instance to change somehow any of layer's parameters, including setting up a mask to replace the initial shape of UIView element with the custom one. Those instruments are IBDesignable/IBInspectable. The goal is to preview our custom views directly through Interface Builder.
So using those keywords we can write our custom class, which will deal only with the single condition whether we need to round corners for our UI element or not.
For example, let's create the class extended from the UIImageView.
#IBDesignable
class UIRoundedImageView: UIImageView {
#IBInspectable var isRoundedCorners: Bool = false {
didSet { setNeedsLayout() }
}
override func layoutSubviews() {
super.layoutSubviews()
if isRoundedCorners {
let shapeLayer = CAShapeLayer()
shapeLayer.path = UIBezierPath(ovalIn:
CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.width, height: bounds.height
)).cgPath
layer.mask = shapeLayer
}
else {
layer.mask = nil
}
}
}
After setting the class name for your UIImageView element (where the dog picture is), in your storyboard, you will get a new option, appeared in the Attributes Inspector menu (details at the screenshot).
The final result should be like this one.
It seems when you add one view as a subview of another that netted view will not necessarily have the same height as its superview. That's what the problem seems like. The solution is to not add your imageView as a subview, but have it on top of your backgroundView. In the image below I'm using a UILabel as my backgroundView.
Also in your case, when you're setting the cornerRadius use this: let radius: CGFloat = self.bounds.size.height / 2.0.
With my hacky solution you'll get smooth corner radius animation alongside frame size change.
Let's say you have ViewSubclass : UIView. It should contain the following code:
class ViewSubclass: UIView {
var animationDuration : TimeInterval?
let imageView = UIImageView()
//some imageView setup code
override func layoutSubviews() {
super.layoutSubviews()
if let duration = animationDuration {
let anim = CABasicAnimation(keyPath: "cornerRadius")
anim.fromValue = self.imageView.cornerRadius
let radius = self.imageView.frame.size.width / 2
anim.toValue = radius
anim.duration = duration
self.imageView.layer.cornerRadius = radius
self.imageView.layer.add(anim, forKey: "cornerRadius")
} else {
imageView.cornerRadius = imageView.frame.size.width / 2
}
animationDuration = nil
}
}
An then you'll have to do this:
let duration = 0.4 //For example
instanceOfViewSubclass.animationDuration = duration
UIView.animate(withDuration: duration, animations: {
//Your animation
instanceOfViewSubclass.layoutIfNeeded()
})
It's not beautiful, and might not work for complex multi-animations, but does answer the question.
Swift 4+ clean solution based on omaralbeik's answer
import UIKit
extension UIImageView {
func setRounded(borderWidth: CGFloat = 0.0, borderColor: UIColor = UIColor.clear) {
layer.cornerRadius = frame.width / 2
layer.masksToBounds = true
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor
}
}
Sample usage in UIViewController
1.Simply rounded UIImageView
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
imageView.setRounded()
}
2.Rounded UIImageView with border width and color
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
imageView.setRounded(borderWidth: 1.0, borderColor: UIColor.red)
}
write this code
override viewDidLayoutSubViews() {
profileImageView.layer.cornerRadius = profileImageView.frame.size.width / 2
profileImageView.clipsToBounds = true
}
in this case it will called after calculating the autolayout calculations in the first code you called the cornerradius code before calculating the actual size of the view cuz it's dynamically calculated using aspect ratio , the actual corner radius is calculated before equaling the width and the height of the view
I have same problem, and Now I get what happened here, hope some ideas can help you:
there are something different between the tows:
your profileImageView in storyboard
your profileImageView in viewDidLoad
the size of bound and frame is different when viewDidLoad and in storyboard,just because view is resize for different device size.
You can try it print(profileImageView.bounds.size) in viewDidLoad and viewDidAppear you will find the size in viewDidLoad you set cornerRadius is not the real "running" size.
a tips for you:
you can use a subClass of ImageView to avoid it, or do not use it in storyboard,
If you have subclassed the UIImageView. Then just add this piece of magical code in it.
Written in : Swift 3
override func layoutSubviews() {
super.layoutSubviews()
if self.isCircular! {
self.layer.cornerRadius = self.bounds.size.width * 0.50
}
}
I am quite new to iOS native development, but I had the same problem and found a solution.
So the green background has this constraints:
backgroundView.translatesAutoresizingMaskIntoConstraints = false
backgroundView.topAnchor.constraint(equalTo: superview!.safeAreaLayoutGuide.topAnchor).isActive = true
backgroundView.leftAnchor.constraint(equalTo: superview!.leftAnchor).isActive = true
backgroundView.widthAnchor.constraint(equalTo: superview!.widthAnchor).isActive = true
backgroundView.heightAnchor.constraint(equalTo: superview!.heightAnchor, multiplier: 0.2).isActive = true
The image constraints:
avatar.translatesAutoresizingMaskIntoConstraints = false
avatar.heightAnchor.constraint(equalTo: backgroundView.heightAnchor, multiplier: 0.8).isActive = true
avatar.widthAnchor.constraint(equalTo: backgroundView.heightAnchor, multiplier: 0.8).isActive = true
avatar.centerYAnchor.constraint(equalTo: backgroundView.centerYAnchor, constant: 0).isActive = true
avatar.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: 20).isActive = true
on viewWillLayoutSubviews() method I set the corner radius
to
avatar.layer.cornerRadius = (self.frame.height * 0.2 * 0.8) / 2
Basically, I am simply calculating the height of the image and then divide it by 2. 0.2 is the backgroungView height constraint multiplier and 0.8 the image width/height constraint multiplier.
Solution: Crop the image
[imageView setImage:[[imageView image] imageWithRoundedCorners:imageView.image.size.width/2]];
imageView.contentMode = UIViewContentModeScaleAspectFill;
I was looking for the same solution for profile pictures. After some hit and try and going through available functions, I came across something which works and is a nice way to ensure its safe. You can use the following function to crop out a round image from the original image and then you need not worry about the corner radius.
Post this even if your view size changes the image remains round and looks good.
Add a 1:1 aspect ratio constraint to the imageView for it to remain circular, despite any height or width changes.
I added custom IBInspectable cornerRadiusPercent, so you can do it without any code.
class RoundButton: UIButton {
override var bounds: CGRect {
didSet {
updateCornerRadius()
}
}
//private var cornerRadiusWatcher : CornerRadiusPercent?
#IBInspectable var cornerRadiusPercent: CGFloat = 0 {
didSet {
updateCornerRadius()
}
}
func updateCornerRadius()
{
layer.cornerRadius = bounds.height * cornerRadiusPercent
}
}
Can be easily done by creating an IBOutlet for the constraint which needs to be changed at runtime. Below is the code:
Create a IBOutlet for the constraint that needs to be changed at run time.
#IBOutlet var widthConstraint: NSLayoutConstraint!
Add below code in viewDidLoad():
self.widthConstraint.constant = imageWidthConstraintConstant()
Below function determines for device types change the width constraint accordingly.
func imageWidthConstraintConstant() -> CGFloat {
switch(self.screenWidth()) {
case 375:
return 100
case 414:
return 120
case 320:
return 77
default:
return 77
}
}

circular image in table view cell swift

I am trying to create some a circular image in every row of my table view. I have followed tutorials but my image is turning out to be a diamond shape and not a circular one. What am I doing wrong:
var cellImage = UIImage(named: pic)
cell.imageView!.image = cellImage
cell.imageView!.layer.frame = CGRectMake(0, 0, 190, 190)
cell.imageView!.layer.borderWidth = 0.5
cell.imageView!.layer.masksToBounds = false
cell.imageView!.layer.borderColor = UIColor.blueColor().CGColor
cell.imageView!.layer.cornerRadius = cell.imageView!.layer.frame.height/2
cell.imageView!.clipsToBounds = true
If you are creating your own imageView, it's better to set the cornerRadius inside the custom TableViewCell.
class CircularTableViewCell: UITableViewCell {
#IBOutlet weak var circularImageView: UIImageView!
override func layoutSubviews() {
circularImageView.layer.cornerRadius = circularImageView.bounds.height / 2
circularImageView.clipsToBounds = true
}
}
Note the cornerRadius property can't guarantee that the view will be absolutely round unless you set the imageView's width and height ratio to be 1:1. Another approach to create round view is using Mask.
public extension UIView {
public func round() {
let width = bounds.width < bounds.height ? bounds.width : bounds.height
let mask = CAShapeLayer()
mask.path = UIBezierPath(ovalInRect: CGRectMake(bounds.midX - width / 2, bounds.midY - width / 2, width, width)).CGPath
self.layer.mask = mask
}
}
This will allow you to call round() with any UIView and make sure the view is always round. e.g.
class CircularTableViewCell: UITableViewCell {
#IBOutlet weak var circularImageView: UIImageView!
override func layoutSubviews() {
circularImageView.round()
}
}
Try giving the static value(half of width or height) as corner radius.This may solve your problem.

How to add shadow to ImageView? [duplicate]

I am trying to create an ImageView that has rounded corners and a shadow to give it some depth. I was able to create a shadow for the UIImageView, but whenever I added the code to also make it have rounded corners, it only had rounded corners with no shadow. I have an IBOutlet named myImage, and it is inside of the viewDidLoad function. Does anybody have any ideas on how to make it work? What am I doing wrong?
override func viewDidLoad() {
super.ViewDidLoad()
myImage.layer.shadowColor = UIColor.black.cgColor
myImage.layer.shadowOpacity = 1
myImage.layer.shadowOffset = CGSize.zero
myImage.layer.shadowRadius = 10
myImage.layer.shadowPath = UIBezierPath(rect: myImage.bounds).cgPath
myImage.layer.shouldRasterize = false
myImage.layer.cornerRadius = 10
myImage.clipsToBounds = true
}
If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. In order to resolve this, you can create two views. The container view should have the shadow, and its subview should have the rounded corners.
The container view has clipsToBounds set to false, and has the shadow properties applied. If you want the shadow to be rounded as well, use the UIBezierPath constructor that takes in a roundedRect and cornerRadius.
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath
Next, set the image view (or any other type of UIView) to be the same size of the container view, set clipsToBounds to true, and give it a cornerRadius.
let myImage = UIImageView(frame: outerView.bounds)
myImage.clipsToBounds = true
myImage.layer.cornerRadius = 10
Finally, remember to make the image view a subview of the container view.
outerView.addSubview(myImage)
The result should look something like this:
Swift 5:
You can use the below extension:
extension UIImageView {
func applyshadowWithCorner(containerView : UIView, cornerRadious : CGFloat){
containerView.clipsToBounds = false
containerView.layer.shadowColor = UIColor.black.cgColor
containerView.layer.shadowOpacity = 1
containerView.layer.shadowOffset = CGSize.zero
containerView.layer.shadowRadius = 10
containerView.layer.cornerRadius = cornerRadious
containerView.layer.shadowPath = UIBezierPath(roundedRect: containerView.bounds, cornerRadius: cornerRadious).cgPath
self.clipsToBounds = true
self.layer.cornerRadius = cornerRadious
}
}
How to use:
Drag a UIView on the storyboard
Drag an ImageView inside that UIView
Storyboard should look like this:
Create IBOutlet for both Views, call extension on your ImageView, and pass above created UIView as an argument.
Here is the output :
Finally here is how to
Properly have an image view, with rounded corners AND shadows.
It's this simple:
First some bringup code ..
class ShadowRoundedImageView: UIView {
override init(frame: CGRect) {
super.init(frame: frame); common() }
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder); common() }
private func common() {
backgroundColor = .clear
clipsToBounds = false
self.layer.addSublayer(shadowLayer)
self.layer.addSublayer(imageLayer) // (in that order)
}
#IBInspectable var image: UIImage? = nil {
didSet {
imageLayer.contents = image?.cgImage
shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
}
}
and then the layers ...
var imageLayer: CALayer = CALayer()
var shadowLayer: CALayer = CALayer()
var shape: UIBezierPath {
return UIBezierPath(roundedRect: bounds, cornerRadius:50)
}
var shapeAsPath: CGPath {
return shape.cgPath
}
var shapeAsMask: CAShapeLayer {
let s = CAShapeLayer()
s.path = shapeAsPath
return s
}
override func layoutSubviews() {
super.layoutSubviews()
imageLayer.frame = bounds
imageLayer.contentsGravity = .resizeAspectFill // (as preferred)
imageLayer.mask = shapeAsMask
shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
shadowLayer.shadowOpacity = 0.80 // etc ...
}
}
Here is the
Explanation
UIImageView is useless, you use a UIView
You need two layers, one for the shadow and one for the image
To round an image layer you use a mask
To round a shadow layer you use a path
For the shadow qualities, obviously add code as you see fit
shadowLayer.shadowOffset = CGSize(width: 0, height: 20)
shadowLayer.shadowColor = UIColor.purple.cgColor
shadowLayer.shadowRadius = 5
shadowLayer.shadowOpacity = 0.80
For the actual shape (the bez path) make it any shape you wish.
(For example this tip https://stackoverflow.com/a/41553784/294884 shows how to make only one or two corners rounded.)
Summary:
• Use two layers on a UIView
Make your bezier and ...
• Use a mask on the image layer
• Use a path on the shadow layer
Here is a another solution (tested code) in swift 2.0
If you set clipsToBounds to true, this will round the corners but prevent the shadow from appearing. So, you can add same size UIView in storyboard behind imageview and we can give shadow to that view
SWIFT 2.0
outerView.layer.cornerRadius = 20.0
outerView.layer.shadowColor = UIColor.blackColor().CGColor
outerView.layer.shadowOffset = CGSizeMake(0, 2)
outerView.layer.shadowOpacity = 1
outerView.backgroundColor = UIColor.whiteColor()
You can use a simple class I have created to add image with rounded corners and shadow directly from Storyboard
You can find the class here

Resources