UITextView
iOS development
user interface
app design
Swift programming

Bordered UITextView

Master System Design with Codemia

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

Introduction

Adding a border to UITextView is simple, but polished results require more than just setting one layer property. Real apps need border states, padding, dark-mode compatibility, and accessibility-safe feedback. A reusable styled component keeps behavior consistent across forms and reduces repetitive controller code.

Base Border Styling

UITextView draws through its layer, so border and corner settings live there.

swift
1import UIKit
2
3let textView = UITextView()
4textView.layer.borderWidth = 1.0
5textView.layer.borderColor = UIColor.systemGray4.cgColor
6textView.layer.cornerRadius = 10
7textView.layer.masksToBounds = true
8textView.backgroundColor = .secondarySystemBackground
9textView.textColor = .label
10textView.font = .preferredFont(forTextStyle: .body)

This gives a clean baseline for most screens.

Improve Input Comfort with Insets

Default text container spacing often feels cramped. Increase insets explicitly:

swift
textView.textContainerInset = UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10)
textView.textContainer.lineFragmentPadding = 0

Setting line fragment padding helps align text with neighboring controls when precise layout is required.

Create a Reusable Subclass

A custom subclass prevents copy-paste style setup.

swift
1import UIKit
2
3final class BorderedTextView: UITextView {
4    override init(frame: CGRect, textContainer: NSTextContainer?) {
5        super.init(frame: frame, textContainer: textContainer)
6        applyStyle()
7    }
8
9    required init?(coder: NSCoder) {
10        super.init(coder: coder)
11        applyStyle()
12    }
13
14    private func applyStyle() {
15        layer.borderWidth = 1
16        layer.borderColor = UIColor.systemGray4.cgColor
17        layer.cornerRadius = 10
18        layer.masksToBounds = true
19
20        backgroundColor = .secondarySystemBackground
21        textColor = .label
22        font = .preferredFont(forTextStyle: .body)
23
24        textContainerInset = UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10)
25        textContainer.lineFragmentPadding = 0
26    }
27}

Register this in design system modules so every screen starts with the same baseline style.

Add Focus and Error States

Borders should communicate field state clearly.

swift
1func setBorderState(isFocused: Bool, hasError: Bool) {
2    if hasError {
3        textView.layer.borderColor = UIColor.systemRed.cgColor
4    } else if isFocused {
5        textView.layer.borderColor = UIColor.systemBlue.cgColor
6    } else {
7        textView.layer.borderColor = UIColor.systemGray4.cgColor
8    }
9}

Combine color changes with text hints for accessibility. Color alone is not sufficient feedback.

Dynamic Type and Accessibility

If users increase text size, bordered text view should still remain readable.

swift
textView.adjustsFontForContentSizeCategory = true

Also test VoiceOver navigation and focus transitions. Border changes triggered by editing state should not conflict with accessibility focus indicators.

Dark Mode and Theming

Avoid hardcoded colors such as fixed light-gray RGB values. Use semantic system colors or theme tokens. This ensures borders stay visible in light and dark mode.

If your app has branded themes, map design tokens to border style in one place so updates do not require touching every screen.

Performance Notes

Layer border settings are cheap, but avoid heavy shadows and complex masks on large numbers of scrolling cells. If many text views appear in table or collection views, preconfigure style in reusable views and avoid repeated expensive updates in cellForRowAt.

Placeholder and Empty State UX

UITextView has no built-in placeholder like UITextField. Many apps add a lightweight placeholder label and hide it when text is non-empty. Keep placeholder color subtle and ensure it remains readable in dark mode.

swift
func updatePlaceholderVisibility(textView: UITextView, placeholderLabel: UILabel) {
    placeholderLabel.isHidden = !textView.text.isEmpty
}

This small enhancement improves usability in feedback and notes screens where users expect field hints.

Common Pitfalls

  • Hardcoding border colors that disappear or look wrong in dark mode.
  • Forgetting text insets, resulting in cramped text appearance.
  • Duplicating style code across multiple view controllers.
  • Using border color as the only validation signal.
  • Applying expensive visual effects that hurt scroll performance.

Summary

  • Use layer properties for border width, color, and corner radius.
  • Add text container insets for better readability.
  • Prefer a reusable subclass to enforce consistent styling.
  • Implement explicit focus and error border states.
  • Validate behavior in dark mode and accessibility settings.

Course illustration
Course illustration

All Rights Reserved.