1

I found this question with a solution to my problem but it still has some misbehavior when I'm using it. How to only show bottom border of UITextField in Swift

In my Project it seems like the bottom border doesn't know the correct width of my UITextField and is longer than my UITextField. The UITextField has constraints to the SaveArea on the left and right and a constraint to the text above. I would say that the width is defined by the constraints at run time so that the code in the extension should be able to get the correct width. But the way my code is getting the width seems to be wrong. Can someone help me?

Code example

Thanks in advance :)

Asperi
  • 228,894
  • 20
  • 464
  • 690
F.M.
  • 630
  • 1
  • 5
  • 18
  • When do you call the addButtonBorder function ? I feel it probably is at a time when perhaps the frame height and width are not accurately calculated yet. – Shawn Frank Feb 03 '22 at 10:10
  • @ShawnFrank Thanks for your respond. I call it in viewDidLoad(). Do I have to call it somewhere else instead? – F.M. Feb 03 '22 at 13:03
  • I don't think your frames would be set as yet in `viewDidLoad`. Just for testing sake, call it in `viewWillAppear` and check if you see a better result. If this works, I can suggest a maybe better solution using autolayout. – Shawn Frank Feb 03 '22 at 14:45
  • `viewWillAppear` didn't worked either. And I tried also autolayout. Nothing result as wanted. I went another approch and left out the extension. Instead I insert a View with a black background, set side constrains the same as the UITextField, top constrain to the UITextfield and a constraint Height of 1. That's probably not the best solution but works so far for me. – F.M. Feb 04 '22 at 09:31

1 Answers1

1

I know you found a workaround but just thought I might add a fix for this if you still were considering using this.

So it seems that your set up was fine but it works a little bit differently on different device sizes.

self.frame.size.width in the extension is not always returning back the correct width of the UITextField in some devices and on orientation changes.

So to get this to work, here are the small changes I made:

extension UITextField
{
    func addBottomBorder() {
        let bottomLine = CALayer()
        
        // The border should be inside the text field
        // so I changed frame.size.height + 5 to
        // frame.size.height - 1
        bottomLine.frame = CGRect(x: 0,
                                  y: frame.size.height-1,
                                  width: frame.size.width,
                                  height: 1)
        
        bottomLine.backgroundColor = UIColor.black.cgColor
        
        borderStyle = .none
        
        layer.addSublayer(bottomLine)
        
        // Add this so the layer does not go beyond the
        // bounds of the text field
        layer.masksToBounds = true
    }
}

After this, the result should be as you hope:

Bottom Border for UITextField in Swift using CALayer AutoLayout

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
  • Hey @Shawn, thank you that you kept thinking about a solution. Sadly that doesn't work out either :( I changed the y value, linke you mentioned and added layer.maskToBounds = true`. But than, no line is shown at all. Without `layer.masksToBounds = true`, the line shows up but has the same misbehavior like before. – F.M. Feb 07 '22 at 08:54
  • @F.M.please can you update your code with the latest. I believe the line is not showing because the position of adding the border is wrong - that's all that needs to be fixed. can you share how did you configure bottomLine.frame please ? – Shawn Frank Feb 07 '22 at 09:00
  • `import UIKit extension UITextField { func addBottomBorder() { let bottomLine = CALayer() bottomLine.frame = CGRect(x: 0, y: frame.size.height+1, width: frame.size.width, height: 1) bottomLine.backgroundColor = UIColor.black.cgColor borderStyle = .none layer.addSublayer(bottomLine) layer.masksToBounds = true } }` – F.M. Feb 10 '22 at 15:11
  • oh crap! Posting code in a command is not beautiful :D I would say that I implemented is the way you said. Just like I said, without `layer.masksToBounds = true` the bottom border is showing but still to long. With that line of code, the bottom border is not showing at all. I'm happy with my workaround so far and have to carry on, so I will stay at my solution. But thank you a lot for your efforts! :) – F.M. Feb 10 '22 at 15:15
  • @F.M. The main issue and difference in your code vs mine is in the line where we set the y coordinate of the border. You are setting your y coordinate at `frame.size.height+1` - this means `outside` your view so you will not see it. I am doing this `frame.size.height-1` which means I am putting it `inside` the view. And please add back the `layer.masksToBounds = true` and I believe you will fix your issue. Please try my code as is without adjusting any values and I think you will see what you are looking for :) – Shawn Frank Feb 10 '22 at 15:30