Here I've got screen designed in Sketch:
There are two buttons. Now I am designing such button in Xcode and I am setting UIButton's corner radius this way:
layer.cornerRadius = 30
clipsToBounds = true
But as the result I am having something strange:
You can see some corner in the center if the left and right sides of button. What can I do?
To generate round corners on such a button, if you set the cornerRadius value to 30, you are assuming that the height of the button is set to 60.
This may not be true on all the devices, depending on how you handle your layout. Seeing your image, it looks like the button is slightly less high than what you designed.
Two options :
Use Auto-Layout and add a constraint of "fixed height" on your button, with a value of 60, so your button always has a height of 60 points.
Implement a UIButton subclass, and in the layoutSubviews method, set the cornerRadius to half the height of the bounds of your button. This way, any time the system re-draws the button, the corner radius will be updated appropriately.
Make a custom UIButton Class and set all of your desired buttons to that class so you don't need to put any more code in every UIViewController class.
The custom UIButton class should look like this:
import UIKit
class RoundCornerButton: UIButton {
override func drawRect(rect: CGRect) {
// Drawing code
self.clipsToBounds = true
self.layer.cornerRadius = self.frame.size.width / 2
}
}
Your button's layer has a different size now, than in Sketch.
After layoutSubviews set the corner radius to be the half of the layers height.
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = layer.bounds.height / 2.0
}
Instead of writing code in every controller if you are going to use multiple times, You can make extension for making circular buttons, views as well using below code.In which you can pass cornerRadius, borderWidth and UIColor.
import UIKit
extension UIView
{
func makeCircular(cornerRadius: CGFloat, borderWidth: CGFloat, borderColor: UIColor)
{
self.layer.cornerRadius = cornerRadius * self.bounds.size.width
self.layer.borderColor = borderColor.CGColor as CGColorRef
self.layer.borderWidth = borderWidth
self.clipsToBounds = true
}
}
you can simply pass the values as per your requirement.
Usage :
snapButton.makeCircular(0.5, borderWidth: 1.0, borderColor: UIColor.clearColor())
Related
I am trying to create custom table view cell which works fine in my other UIViewControllers. However, in one of my controllers, the shadow is not growing, I can barely see the shadow.
Here is an image of the shadow being shown in red, you can see it is barely visible.
My cell has a UIView added inside the contentView to creating floating cell effects - the same code and same storyboard layouts are being used across my controllers but this is the only table view where the shadow issue is occurring - so I must be missing something.
My addShadow extension:
extension UIView {
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
}
}
My awakeFromNib on the custom cell:
:: cellContentView is my UIView added to the base contentView of the cell.
override func awakeFromNib() {
super.awakeFromNib()
self.backgroundColor = .clear
self.selectionStyle = .none
cellContentView?.layer.masksToBounds = true
cellContentView?.round(corners: [.topLeft, .topRight, .bottomLeft, .bottomRight], radius: 10)
cellContentView?.addShadow(offset: CGSize(width: 40, height: 60), color: UIColor.red, radius: 10, opacity: 1)
cellContentView?.layer.shouldRasterize = true
}
Note: The .round is an extension being used on all my cells.
No matter what radius or offset I add for this shadow, it does not get bigger than the image. Also, none of my other cells in the their controllers require the shouldRasterize property to be set, but this does.
Does anyone know what is happening here?
Thanks :)
Edit
Strangely, if I add constraints around my view to keep the gaps large between my view and the cell content view, the background colour disappears - this is set to white in the storyboard.
You should call in the layoutSubviews method. because shadow should add after the view is uploaded
override func awakeFromNib() {
super.awakeFromNib()
//init methods
}
override public func layoutSubviews() {
super.layoutSubviews()
//Added shadow
self.reloadLayers()
}
private func reloadLayers() {
self.layer.cornerRadius = 5
self.addShadow(.TransactionCell)
}
I hope it helps
Content view will fill you cell, so you need to add shadow to view inside content view which has all your components inside it. Then add constraints to it with gap between that view and content view. Second, 40 and 60 properties for shadow is likely too large, when I said too large I mean unbelievable large, because gap between content views in cells are no more than 15 - 30 even less. so try it with much less values, while radius can remain 10 but you will see what value fit the best. If cell content view is your custom view just values will did the job if your view is not kind of transparent or any inside it, in that case it won't, and there is hard to fix that, I tried many libraries and custom codes and it is never ok.
squircleView.layer.cornerRadius = 40
squircleView.layer.cornerCurve = CALayerCornerCurve.continuous
squircleView.layer.shadowColor = UIColor.systemGray.cgColor
squircleView.layer.shadowOpacity = 0.7
squircleView.layer.shadowOffset = CGSize(width: 0, height: 0.5)
squircleView.layer.shadowRadius = 5
ModernBoldButton is a subclass of UIButton, here is a snippet of it:
private func commonInit() {
insertSubview(blurView, at: 0)
if let imageView = imageView {
bringSubviewToFront(imageView)
}
if let titleLabel = titleLabel {
bringSubviewToFront(titleLabel)
}
backgroundColor = .clear
clipsToBounds = true
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.width / 2
}
I have four UIButton's embedeed in stack view and as you can see on the screenshot, all of the buttons have incorrect shapes, they should look like a circle.
I suspect that I should set the cornerRadius somewhere else in my code, but where?
In order for them to look like a circle, your bounds must be a square. It appears that this is not the case for your buttons (the width is larger than the height).
You could add some constraints to your buttons in order to maintain a 1/1 ratio.
Other than that, you're setting it in the right place.
Rounding to with/2 will completely rounded top and bottom sides (eye shape 👁)
Rounding to height/2 will completely rounded left and right sides (like this ())
So if you want a circle, you need to make sure both width and height sizes are the same like a square.
In order to doo it automatically, you can use autolayout and the stackView will take care of the sizing:
self.translatesAutoresizingMaskIntoConstraints = false
self.heightAnchor.constraint(equalTo: self.widthAnchor).isActive = true
Make sure to do it just once to avoid duplications.
I have a few views whose size is not hardcoded, but determined via constraints and I need those views to be round.
Is there a way to set the cornerRadius property "dynamically", e.g. depending on the actual size of the object?
I know that if this view is inside a UIViewController, I can get the width via roundView.frame.width and set the layer.cornerRadius property there, but the round views aren't contained in a viewController, but managed by another simple UIView.
Thank you in advance!
Dave
You can override layoutSubviews method of View class and set the cornerRadius value there. Lets say you want cornerRadius to be half of width of the view:
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width * 0.5
}
Easy to achieve this with RxSwift by observing Key Path.
extension UIView{
func cornerHalf(){
clipsToBounds = true
rx.observe(CGRect.self, #keyPath(UIView.bounds))
.subscribe(onNext: { _ in
self.layer.cornerRadius = self.bounds.width * 0.5
}).disposed(by: rx.disposeBag)
}
}
Just call in init method, the code seems simpler by declaration , instead of being distributed two place. Especially, the logic is commonly exsited in your project.
Call like this:
let update: UIButton = {
let btn = UIButton()
// more config
btn.cornerHalf()
return btn
}()
Just access them through your simple view that contains them. If your simple container view doesn't have those round view as instances, then you can access them by iterating through its subviews array.
When you get a hold of the view you can access their frame.size.width and set the layer.corner radius property to that value.
I have a rectangular view that I want "perfectly" round borders on the ends. I'm rounding the corners like so:
contentView.layer.cornerRadius = 30; //arbitrary number
contentView.layer.borderWidth = 1.0
contentView.layer.borderColor = UIColor.white.cgColor
And this is my result:
And this is the result I'm aiming for:
I'd like to determine the cornerRadius for my view to achieve rounded ends dynamically. Any ideas? Thanks!
You’re on the right way. Somewhat conventional approach to do it looks like this:
contentView.layer.cornerRadius = contentView.bounds.height / 2
If your "contentView" is a class that inherits from a UIView then:
class CustomView: UIView
{
...
override func layoutSubviews()
{
super.layoutSubviews() //Don't want to change the default behavior of this func. Just want to add to it.
layer.cornerRadius = bounds.height / 2
}
...
}
If it's just a plain UIView in a UIViewController, then you can update it in the UIViewController's viewWillAppear(_ animated: Bool) method.
The class given below is working fine
#IBDesignable class iButton : UIButton {
#IBInspectable var cornerRadius : CGFloat = 0.0{
didSet{
layer.cornerRadius = cornerRadius
}
}}
But question is, when i set cornerRadius value 35 in Attribute Inspector for the button with size of (width : 70, Height 70). Im getting rounded button on the storyboard but while running it on Simulator its not circular instead its rounded rectangle.
My Design View on xCode is iPhone-SE and simulated on iPhone-7-plus simulator.
I have also enabled autoresize by setting the height and width on the Size Inspector.
Out of my knowledge the corner radius should be the half of the width. And when the button is resized by auto-resizing why not the corner radius is resized. how can i fix this?
Thanks in advance.
import UIKit
#IBDesignable
class RoundedCornerButton: UIButton {
override func drawRect(rect: CGRect) {
self.clipsToBounds = true
}
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
self.layer.cornerRadius = cornerRadius
}
}
}
or you can check this link this link for more info
https://www.youtube.com/watch?v=JQ5i2YKwvJ8
Thank You i got answer.
We also need to scale the cornerRadius.
layer.cornerRadius = cornerRadius * (UIScreen.main.bounds.width/320.0) //320.0 be my width of the screen that i designed on storyboard