Swift
SwiftUI
Objective-C
Xamarin
UITextField

Add bottom border line to UI TextField view in SwiftUI / Swift / Objective-C / Xamarin

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A bottom-only border is a common design pattern for text input fields because it looks lighter than the default rounded UITextField border. The exact implementation depends on the UI framework, but the basic idea is always the same: remove the standard border and draw a thin line at the bottom edge.

This article shows practical ways to do that in SwiftUI, UIKit with Swift, Objective-C, and Xamarin.iOS. The code is intentionally small so you can drop it into a real form without rebuilding the whole screen.

SwiftUI

SwiftUI does not expose a direct “bottom border only” style for TextField, so the usual approach is an overlay or background line.

swift
1import SwiftUI
2
3struct ContentView: View {
4    @State private var username = ""
5
6    var body: some View {
7        TextField("Username", text: $username)
8            .padding(.vertical, 8)
9            .overlay(
10                Rectangle()
11                    .frame(height: 1)
12                    .foregroundColor(.gray),
13                alignment: .bottom
14            )
15            .padding()
16    }
17}

This keeps the field declarative and easy to theme. You can swap the foregroundColor based on focus state or validation errors.

UIKit In Swift

In UIKit, the most common pattern is to remove the built-in border and add a sublayer.

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    let textField = UITextField()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        textField.frame = CGRect(x: 20, y: 120, width: 240, height: 40)
10        textField.borderStyle = .none
11        view.addSubview(textField)
12    }
13
14    override func viewDidLayoutSubviews() {
15        super.viewDidLayoutSubviews()
16
17        textField.layer.sublayers?
18            .removeAll(where: { $0.name == "bottomBorder" })
19
20        let border = CALayer()
21        border.name = "bottomBorder"
22        border.backgroundColor = UIColor.lightGray.cgColor
23        border.frame = CGRect(x: 0, y: textField.bounds.height - 1, width: textField.bounds.width, height: 1)
24        textField.layer.addSublayer(border)
25    }
26}

Doing the layout work in viewDidLayoutSubviews ensures the line matches the final field size.

Objective-C

The Objective-C version uses the same CALayer idea.

objective-c
1- (void)viewDidLoad {
2    [super viewDidLoad];
3
4    self.textField.borderStyle = UITextBorderStyleNone;
5}
6
7- (void)viewDidLayoutSubviews {
8    [super viewDidLayoutSubviews];
9
10    CALayer *border = [CALayer layer];
11    border.backgroundColor = [UIColor lightGrayColor].CGColor;
12    border.frame = CGRectMake(0,
13                              self.textField.bounds.size.height - 1,
14                              self.textField.bounds.size.width,
15                              1);
16    [self.textField.layer addSublayer:border];
17}

If layout runs more than once, clear or reuse existing layers so you do not stack multiple borders on top of each other.

Xamarin.iOS

In Xamarin.iOS, the same technique applies through C# bindings.

csharp
1using CoreAnimation;
2using CoreGraphics;
3using UIKit;
4
5public override void ViewDidLayoutSubviews()
6{
7    base.ViewDidLayoutSubviews();
8
9    TextField.BorderStyle = UITextBorderStyle.None;
10
11    var border = new CALayer();
12    border.Name = "bottomBorder";
13    border.BackgroundColor = UIColor.LightGray.CGColor;
14    border.Frame = new CGRect(0, TextField.Bounds.Height - 1, TextField.Bounds.Width, 1);
15
16    TextField.Layer.AddSublayer(border);
17}

As with UIKit, avoid adding duplicate sublayers every time the layout cycle runs.

Focus And Validation Styling

A static gray line is the simplest version, but bottom borders are often more useful when they respond to focus or error state. In SwiftUI, that might mean changing the line color with @FocusState. In UIKit or Xamarin, you can update the border layer color in editing callbacks such as editingDidBegin and editingDidEnd.

That small detail makes the border feel like part of the interaction model rather than a purely decorative line.

Common Pitfalls

  • Forgetting to disable the default UITextField border style.
  • Adding a new bottom-border layer on every layout pass without removing the old one.
  • Calculating the border frame before Auto Layout has finished.
  • Styling only the line and forgetting focus or error feedback.
  • Expecting SwiftUI TextField to support a built-in bottom-border mode.

Summary

  • In all frameworks, the pattern is to remove the default border and draw a line at the bottom edge.
  • SwiftUI usually uses overlay with a Rectangle.
  • UIKit, Objective-C, and Xamarin typically use a CALayer.
  • Perform frame-based border layout after the field has its final size.
  • Reuse or clear border layers so repeated layout passes do not create duplicates.

Course illustration
Course illustration

All Rights Reserved.