Borders not covering background
Asked Answered
O

1

4

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:

enter image description here

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
    }
Oaxaca answered 26/10, 2015 at 16:21 Comment(8)
Try using borderWidth = 6 or borderWidth = 5.5. That may fix it.Ashelman
Thanks, but I've already tried that, and it doesn't change anything. I think borders are calculated from the edge, and created inwards.Oaxaca
Try removing maskToBounds or setting it to false perhaps?Ashelman
Without that, then the label remains a square, with all four corners sticking out. That's how it knows to clip the edges off with cornerRadius. No dice.Oaxaca
Do you know the exact frame of the label? You may want to set it to the integral version (CGRectIntegral)Seychelles
@Wain, I'm not familier with this. Is this as simple as changing my code to iconLbl.frame = CGRectMake(theWidth/2-20, bottomView.frame.minY-20, 40, 40).integral ? if so, then there are no changesOaxaca
You can change iconLbl.layer.frame if that helps anyone, but it doesn't seem to effect it.Ashelman
Thanks Charles, but still no cigar. I've got a feeling I'm gonna be putting this label in a larger view, instead of fussing around with a border, but it just feels so... wrong...Oaxaca
M
1

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

Melba answered 12/10, 2020 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.