UITextField border isn't clipping - swift

I'm almost sure this question has been asked before, but I searched for almost an hour and didn't find anything
This is my code:
textField.font = UIFont.systemFont(ofSize: 12.0)
textField.layer.borderWidth = 0.9
textField.placeholder = "border is 0.9 clip is false"
textField.layer.borderColor = UIColor.black.cgColor
textField.borderStyle = UITextBorderStyle.roundedRect
textField.returnKeyType = UIReturnKeyType.done
Doesn't matter if set textField.clipsToBounds to true or false, the borders won't be rounded. However if I change the background color, it will fill it as it has a rounded border, see the image below.
if you zoom in, you'll see that the it doesn't fill the corners completely
If I set textField.layer.borderWidth = 0.1 then I would have a nice roundedRect, but they border would then have to be a thin line. See the image below:
again setting clipToBounds = true won't make any difference.
EDIT:
So the answer is to do textField.layer.cornerRadius = 5. But then I wonder what is the UITextBorderStyle.roundedRect doing then?!

Try textField.layer.cornerRadius = 5
cornerRadius - the radius to use when drawing rounded corners for the layer’s background. Animatable.
var cornerRadius: CGFloat { get set }
Setting the radius to a value greater than 0.0 causes the layer to
begin drawing rounded corners on its background. By default, the
corner radius does not apply to the image in the layer’s contents
property; it applies only to the background color and border of the
layer. However, setting the masksToBounds property to true causes the
content to be clipped to the rounded corners.
The default value of this property is 0.0.
Update:
But then I wonder what is the UITextBorderStyle.roundedRect doing then?
Basically the same thing but with default radius. Maybe it was overwritten somewhere. Check out your IB properties, in Attribute Inspector, Border Style property:

Related

UITextfield shadow

I want to add shadow to my UITextfield I tried code below, shadows work fine, but there is one thing, it is also set on the text inside my UITextfield any solutions ?
passwordTextField.layer.masksToBounds = false
passwordTextField.layer.shadowRadius = 4.0
passwordTextField.layer.shadowColor = UIColor.black.cgColor
passwordTextField.layer.shadowOffset = CGSize(width: 1.0, height: 1.0)
passwordTextField.layer.shadowOpacity = 1.0
picture for better understanding:
as you can see on the picture above, shadow is also set on textfield, how can I only set shadow to corner?
You should be able to just set the textfield background color to white and it will remove the text shadow.
passwordTextField.backgroundColor = .white // or whatever color you need

add two shadows with different colors on UIView?

I am going to make 3D effect to uiview and add shadows like in the following image. there is white shadow on top and left sides and gray shadow on right and bottom side.
I already added white shadow on top and left sides.
my result
self.layer.shadowColor = UIColor.white.cgColor
self.layer.shadowOffset = CGSize(width: -4.0, height: -4.0)
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 1.0
self.layer.masksToBounds = false
Is it possible to achieve the following result by uibezierPath?
Image
Try adding a creating another layer with the other shadow color and change the offset. Then add this sublayer underneath
layer.addsubview(yourNewView)

Rounded corners of an image

I'm experiencing something very weird. I have a custom UICollectionViewCell that has a UIImageView. Now, I'm setting the cornerRadius of the UIImageView to be rounded and it works on some images, but for others, it produces results like this:
You can clearly see the top and the bottom of the image are not rounded and I'm not sure what causes this. I assume it has to do with the width/height of the image, but I cant figure it out.
I'm using this tiny extension on UIImageView to set the rounded images.
extension UIImageView {
func makeRounded() {
let radius = self.bounds.height / 2.0
self.layer.cornerRadius = radius
self.layer.masksToBounds = true
self.clipsToBounds = true
}
}
I tried changing the self.bounds.height to self.bounds.width, no change. I tried using self.frame.height, self.frame.size.height, self.frame.width, all produces the same result.
It has nothing to with cornerRadius, your code (makeRounded()) should make it rounded.
The issue is related to the contentMode of the image view. If you tried to add a background color to it, you should be able to understand exactly what's the issue, so let's say set the backgroundColor as .red, you should see a red circle containing the image in the middle.
To fix it, you should choose a content mode that will fill the whole image view, such as .scaleToFill or .scaleAspectFill:
extension UIImageView {
func makeRounded() {
let radius = self.bounds.height / 2.0
self.layer.cornerRadius = radius
self.layer.masksToBounds = true
self.clipsToBounds = true
// add this one:
self.contentMode = .scaleAspectFill
}
}

macOS: CALayer shadow not showing

I need a shadow on my view. I tried using the view’s NSShadow capability, but it is too slow to use in a scroll view. I want to try using the layer’s shadow properties to hopefully improve performance.
In my NSView.updateLayer() method, I set the following properties:
layer.shadowOffset = CGSize(width: 0, height: -3)
layer.shadowRadius = 3
layer.shadowColor = NSColor.black().cgColor
layer.shadowOpacity = 0.3
No shadow is shown. I tried also setting NSView.wantsDefaultClipping and CALayer.masksToBounds to false, but there is still no shadow.
Why is there no shadow when using the CALayer shadow properties?
What you need to add is:
self.view.wantsLayer = true
I tried running the following code; the layer does show as well as the shadow:
let layer = CALayer()
layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
layer.backgroundColor = NSColor.redColor().CGColor
layer.shadowOffset = CGSize(width: 0, height: -3)
layer.shadowRadius = 3
layer.shadowColor = NSColor.blackColor().CGColor
layer.shadowOpacity = 1.0 //Or: 0.3 as you originally have
self.view.wantsLayer = true
self.view.layer?.addSublayer(layer)
By the way, you have a typo on the following line:
NSColor.black().cgColor
as it should be:
NSColor.blackColor().CGColor
I looked at the disassembly of CALayer.render(in:) and it looked like it was properly accessing the layer shadow properties. So NSView probably overwrites the layer shadow properties with its own on every draw cycle. The bottom line is that you can only add shadows to view-backing layers by using the shadow property on the view.
I did solve my scroll performance problem though. I profiled my app during a scroll and noticed that the creation of the shadow image in CGContextEndTransparencyLayer was causing the CPU to spike.
There are two steps for creating a shadow. First, a path for the shadow has to be computed based on the alpha channel of the pixels above. Second, a gaussian blur is applied in order to soften the edges of the shadow.
Since I know the view on top of the shadow is fully opaque, I know the path will be simply the view’s bounds. I could have skipped the first step by setting the layer’s shadowPath property. But unfortunately, the layer’s shadow properties are overridden by the view which doesn’t have a shadowPath property.
My solution was to create a container view that draws a rectangular shadow image underneath the content view. This shadow image is created once and cached, increasing scroll performance dramatically. And thanks to the power of Auto Layout (specifically, the alignment rect insets), the container view can be used without having to manually adjust for the shadow.
You can view my code on GitHub.
NSView sets the shadow related properties on CALayer at predictable times, like when wantsLayer is set to true and when the view is added to a superview. Set the layer shadow properties after NSView and the shadow will be visible. I set the shadow properties during resizeSubviews.

Borders not covering background

I've got a UILabel is using a border the same color as a background which it is half obscuring, to create a nice visual effect. However the problem is that there is still a tiny, yet noticeable, sliver of the label's background color on the OUTSIDE of the border.
The border is not covering the whole label!
Changing the border width doesn't change anything either, sadly.
Here's a picture of what's going on, enlarged so you can see it:
And my code follows:
iconLbl.frame = CGRectMake(theWidth/2-20, bottomView.frame.minY-20, 40, 40)
iconLbl.font = UIFont.fontAwesomeOfSize(23)
iconLbl.text = String.fontAwesomeIconWithName(.Info)
iconLbl.layer.masksToBounds = true
iconLbl.layer.cornerRadius = iconLbl.frame.size.width/2
iconLbl.layer.borderWidth = 5
iconLbl.layer.borderColor = topBackgroundColor.CGColor
iconLbl.backgroundColor = UIColor.cyanColor()
iconLbl.textColor = UIColor.whiteColor()
Is there something I'm missing?
Or am I going to have to figure out another to achieve this effect?
Thanks!
EDIT:
List of things I've tried so far!
Changing layer.borderWidth
Fussing around with clipsToBounds/MasksToBounds
Playing around the the layer.frame
Playing around with an integral frame
EDIT 2:
No fix was found! I used a workaround by extending this method on to my UIViewController
func makeFakeBorder(inputView:UIView,width:CGFloat,color:UIColor) -> UIView {
let fakeBorder = UIView()
fakeBorder.frame = CGRectMake(inputView.frame.origin.x-width, inputView.frame.origin.y-width, inputView.frame.size.width+width*2, inputView.frame.size.height+width*2)
fakeBorder.backgroundColor = color
fakeBorder.clipsToBounds = true
fakeBorder.layer.cornerRadius = fakeBorder.frame.size.width/2
fakeBorder.addSubview(inputView)
inputView.center = CGPointMake(fakeBorder.frame.size.width/2, fakeBorder.frame.size.height/2)
return fakeBorder
}
I believe this is the way a border is drawn to a layer in iOS. In the document it says:
When this value is greater than 0.0, the layer draws a border using the current borderColor value. The border is drawn inset from the receiver’s bounds by the value specified in this property. It is composited above the receiver’s contents and sublayers and includes the effects of the cornerRadius property.
One way to fix this is to apply a mask to a view's layer, but I found out that even if so we still can see a teeny tiny line around the view when doing snapshot tests. So to fix it more, I put this code to layoutSubviews
class MyView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
let maskInset: CGFloat = 1
// Extends the layer's frame.
layer.frame = layer.frame.inset(dx: -maskInset, dy: -maskInset)
// Increase the border width
layer.borderWidth = layer.borderWidth + maskInset
layer.cornerRadius = bounds.height / 2
layer.maskToBounds = true
// Create a circle shape layer with true bounds.
let mask = CAShapeLayer()
mask.path = UIBezierPath(ovalIn: bounds.inset(dx: maskInset, dy: maskInset)).cgPath
layer.mask = mask
}
}
CALayer's mask