summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN/CustomTextView.swift
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-02-22 12:45:28 +0100
committerAndrej Mihajlov <and@mullvad.net>2021-02-24 11:19:07 +0100
commitd3816ce772bf1a050f8a33d73e25ed3efec7c885 (patch)
tree42a5d4c004baf0a396d8da27099fa6a604f99e65 /ios/MullvadVPN/CustomTextView.swift
parent1cf9b1e0a2c4f319eccdc7ca05ee2134f0ee13d9 (diff)
downloadmullvadvpn-d3816ce772bf1a050f8a33d73e25ed3efec7c885.tar.xz
mullvadvpn-d3816ce772bf1a050f8a33d73e25ed3efec7c885.zip
Add custom text field & text view
Diffstat (limited to 'ios/MullvadVPN/CustomTextView.swift')
-rw-r--r--ios/MullvadVPN/CustomTextView.swift124
1 files changed, 124 insertions, 0 deletions
diff --git a/ios/MullvadVPN/CustomTextView.swift b/ios/MullvadVPN/CustomTextView.swift
new file mode 100644
index 0000000000..3ce1fa9466
--- /dev/null
+++ b/ios/MullvadVPN/CustomTextView.swift
@@ -0,0 +1,124 @@
+//
+// CustomTextView.swift
+// MullvadVPN
+//
+// Created by pronebird on 16/09/2020.
+// Copyright © 2020 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+private let kTextViewCornerRadius = CGFloat(4)
+
+class CustomTextView: UITextView {
+
+ var roundCorners: Bool = true {
+ didSet {
+ layer.cornerRadius = roundCorners ? kTextViewCornerRadius : 0
+ }
+ }
+
+ /// Placeholder string
+ var placeholder: String? {
+ set {
+ placeholderTextLabel.text = newValue
+ }
+ get {
+ return placeholderTextLabel.text
+ }
+ }
+
+ /// Placeholder text label
+ private let placeholderTextLabel = UILabel()
+
+ /// Placeholder label constraints
+ private var placeholderConstraints = [NSLayoutConstraint]()
+
+ override var textContainerInset: UIEdgeInsets {
+ didSet {
+ setNeedsUpdateConstraints()
+ }
+ }
+
+ override var font: UIFont? {
+ didSet {
+ placeholderTextLabel.font = self.font ?? UIFont.preferredFont(forTextStyle: .body)
+ }
+ }
+
+ /// Placeholder text inset derived from `textContainerInset`
+ private var placeholderTextInset: UIEdgeInsets {
+ var placeholderInset = textContainerInset
+
+ // Offset the placeholder label to match with text view rendering.
+ placeholderInset.top += 0.5
+
+ return placeholderInset
+ }
+
+ override init(frame: CGRect, textContainer: NSTextContainer?) {
+ super.init(frame: frame, textContainer: textContainer)
+
+ placeholderTextLabel.textColor = UIColor.TextField.placeholderTextColor
+ placeholderTextLabel.highlightedTextColor = UIColor.TextField.placeholderTextColor
+ placeholderTextLabel.translatesAutoresizingMaskIntoConstraints = false
+ addSubview(placeholderTextLabel)
+
+ // Create placeholder constraints
+ placeholderConstraints = [
+ placeholderTextLabel.topAnchor.constraint(equalTo: topAnchor),
+ placeholderTextLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
+ placeholderTextLabel.trailingAnchor.constraint(equalTo: trailingAnchor)
+ ]
+ NSLayoutConstraint.activate(placeholderConstraints)
+
+ // Set visual appearance
+ textColor = UIColor.TextField.textColor
+ layer.cornerRadius = kTextViewCornerRadius
+ clipsToBounds = true
+
+ // Set content padding
+ contentInset = .zero
+ textContainerInset = UIEdgeInsets(top: 12, left: 14, bottom: 12, right: 14)
+ self.textContainer.lineFragmentPadding = 0
+
+ // Handle placeholder visibility
+ NotificationCenter.default.addObserver(
+ forName: NSTextStorage.didProcessEditingNotification,
+ object: textStorage,
+ queue: OperationQueue.main) { [weak self] (note) in
+ self?.updatePlaceholderVisibility()
+ }
+
+ updatePlaceholderVisibility()
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func updateConstraints() {
+ let textInset = placeholderTextInset
+
+ for constraint in placeholderConstraints {
+ switch constraint.firstAttribute {
+ case .top:
+ constraint.constant = textInset.top
+ case .leading:
+ constraint.constant = textInset.left
+ case .trailing:
+ constraint.constant = textInset.right
+ default:
+ break
+ }
+ }
+
+ super.updateConstraints()
+ }
+
+ private func updatePlaceholderVisibility() {
+ placeholderTextLabel.isHidden = textStorage.length > 0
+ }
+
+}