Customize PDF Form Appearance in Swift for iOS

Customize the Appearance of Forms. Get additional resources by visiting our guide on supported PDF form fields in iOS.


//
// Copyright © 2020-2025 PSPDFKit GmbH. All rights reserved.
//
// The Nutrient sample applications are licensed with a modified BSD license.
// Please see License for details. This notice may not be removed from this file.
//
import PSPDFKit
import PSPDFKitUI
/// This example shows how to customize the appearance of forms. We also add a
/// temporary label over text and signature fields which will disappear when
/// we type anything in the fields.
class CustomizingFormAppearanceExample: Example {
override init() {
super.init()
title = "Customizing the Appearance of Forms"
category = .forms
priority = 10
}
let document = AssetLoader.writableDocument(for: "Form.pdf", overrideIfExists: true)
override func invoke(with delegate: ExampleRunnerDelegate) -> UIViewController {
/// These options clear out the default form field color so that
/// we can customize it dynamically later in the example.
let options = document.renderOptions(forType: .page)
options.drawSignHereOverlay = false
options.interactiveFormFillColor = UIColor.clear
document.setRenderOptions(options, type: .page)
let controller = PDFViewController(document: document) {
$0.pageTransition = .scrollPerSpread
$0.overrideClass(PDFPageView.self, with: CustomFormPDFPageView.self)
}
controller.delegate = self
styleTextFieldFormElements()
return controller
}
func styleTextFieldFormElements() {
let annotations = document.annotationsForPage(at: 0, type: .widget)
for annotation in annotations {
if let formElement = annotation as? TextFieldFormElement {
formElement.highlightColor = UIColor.clear
formElement.fillColor = UIColor(red: 221.0 / 255.0, green: 240.0 / 255.0, blue: 236.0 / 255.0, alpha: 1)
formElement.borderColor = UIColor.clear
formElement.borderStyle = .none
formElement.borderEffectIntensity = 0.0
}
}
}
}
extension CustomizingFormAppearanceExample: PDFViewControllerDelegate {
func pdfViewController(_ pdfController: PDFViewController, willBeginDisplaying pageView: PDFPageView, forPageAt pageIndex: Int) {
if let pageView = pageView as? CustomFormPDFPageView {
pageView.addLabels()
}
}
}
private class CustomFormPDFPageView: PDFPageView {
/// Dictionary which keeps a mapping between the form element and its label.
/// Used to identify which label to remove when selecting a form field.
var labelList = [String: UILabel]()
override var frame: CGRect {
didSet {
// Re-add labels when page view frame changes
labelList.values.forEach { $0.removeFromSuperview() }
labelList.removeAll()
addLabels()
}
}
/// `prepareForReuse` automatically removes all unknown internal subviews.
/// We need to clear out our mapping dictionary as well.
override func prepareForReuse() {
labelList.removeAll()
super.prepareForReuse()
}
/// Add labels over all the text and signature fields.
func addLabels() {
guard let document = presentationContext?.document else { return }
let annotations = document.annotationsForPage(at: pageIndex, type: .widget)
for annotation in annotations {
if let formElement = annotation as? FormElement {
addLabelOnFormElement(formElement: formElement)
}
}
}
/// Add the label on a given form element. Only add a label if the form field is empty.
func addLabelOnFormElement(formElement: FormElement) {
if !(formElement.isKind(of: TextFieldFormElement.self) || formElement.isKind(of: SignatureFormElement.self)) { return }
let label = labelList[formElement.uuid] ?? UILabel()
if let textFieldFormElement = formElement as? TextFieldFormElement {
if textFieldFormElement.contents != nil && textFieldFormElement.contents != "" { return }
label.text = textFieldFormElement.textFormField?.name ?? "Text Field"
}
if let signatureFormElement = formElement as? SignatureFormElement {
if signatureFormElement.isSigned || signatureFormElement.overlappingSignatureAnnotation != nil { return }
label.text = "Signature Field"
}
label.frame = convert(formElement.boundingBox, from: pdfCoordinateSpace)
label.textAlignment = .center
label.textColor = UIColor(red: 84.0 / 255.0, green: 178.0 / 255.0, blue: 159.0 / 255.0, alpha: 1)
label.backgroundColor = UIColor(red: 221.0 / 255.0, green: 240.0 / 255.0, blue: 236.0 / 255.0, alpha: 1)
annotationContainerView.addSubview(label)
labelList[formElement.uuid] = label
}
override func didSelect(_ annotations: [Annotation]) {
super.didSelect(annotations)
for annotation in annotations {
if let label = labelList[annotation.uuid] {
labelList[annotation.uuid] = nil
label.removeFromSuperview()
}
if let textFieldFormElement = annotation as? TextFieldFormElement {
textFieldFormElement.borderColor = UIColor(red: 84.0 / 255.0, green: 178.0 / 255.0, blue: 159.0 / 255.0, alpha: 1)
textFieldFormElement.borderStyle = .solid
textFieldFormElement.borderEffectIntensity = 1.0
}
}
}
override func didDeselect(_ annotations: [Annotation]) {
super.didDeselect(annotations)
for annotation in annotations {
if let textFieldFormElement = annotation as? TextFieldFormElement {
textFieldFormElement.borderColor = UIColor.clear
textFieldFormElement.borderStyle = .none
textFieldFormElement.borderEffectIntensity = 0.0
}
if let formElement = annotation as? FormElement {
addLabelOnFormElement(formElement: formElement)
}
if let inkAnnotation = annotation as? InkAnnotation {
if inkAnnotation.isSignature { addLabels() }
}
}
}
}

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.