Antidote/Antidote/ExtendedTextField.swift

225 lines
5.8 KiB
Swift

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import UIKit
import SnapKit
private struct Constants {
static let TextFieldHeight = 40.0
static let VerticalOffset = 5.0
}
protocol ExtendedTextFieldDelegate: class {
func loginExtendedTextFieldReturnKeyPressed(_ field: ExtendedTextField)
}
class ExtendedTextField: UIView {
enum FieldType {
case login
case normal
}
weak var delegate: ExtendedTextFieldDelegate?
var maxTextUTF8Length: Int = Int.max
var title: String? {
get {
return titleLabel.text
}
set {
titleLabel.text = newValue
}
}
var placeholder: String? {
get {
return textField.placeholder
}
set {
textField.placeholder = newValue
}
}
var text: String? {
get {
return textField.text
}
set {
textField.text = newValue
}
}
var hint: String? {
get {
return hintLabel.text
}
set {
hintLabel.text = newValue
}
}
var secureTextEntry: Bool {
get {
return textField.isSecureTextEntry
}
set {
textField.isSecureTextEntry = newValue
}
}
var returnKeyType: UIReturnKeyType {
get {
return textField.returnKeyType
}
set {
textField.returnKeyType = newValue
}
}
fileprivate var titleLabel: UILabel!
fileprivate var textField: UITextField!
fileprivate var hintLabel: UILabel!
init(theme: Theme, type: FieldType) {
super.init(frame: CGRect.zero)
createViews(theme: theme, type: type)
installConstraints()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func becomeFirstResponder() -> Bool {
return textField.becomeFirstResponder()
}
}
extension ExtendedTextField: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
delegate?.loginExtendedTextFieldReturnKeyPressed(self)
return false
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let resultText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
if resultText.lengthOfBytes(using: String.Encoding.utf8) <= maxTextUTF8Length {
return true
}
textField.text = resultText.substringToByteLength(maxTextUTF8Length, encoding: String.Encoding.utf8)
return false
}
}
// Accessibility
extension ExtendedTextField {
override var isAccessibilityElement: Bool {
get {
return true
}
set {}
}
override var accessibilityLabel: String? {
get {
return placeholder ?? title
}
set {}
}
override var accessibilityHint: String? {
get {
var result: String?
if placeholder != nil {
// If there is a placeholder also read title as part of the hint.
result = title
}
switch (result, hint) {
case (.none, _):
return hint
case (.some, .none):
return result
case (.some(let r), .some(let s)):
return "\(r), \(s)"
}
}
set {}
}
override var accessibilityValue: String? {
get {
return text
}
set {}
}
override var accessibilityTraits: UIAccessibilityTraits {
get {
return textField.accessibilityTraits
}
set {}
}
}
private extension ExtendedTextField {
func createViews(theme: Theme, type: FieldType) {
textField = UITextField()
textField.delegate = self
textField.borderStyle = .roundedRect
textField.autocapitalizationType = .sentences
textField.enablesReturnKeyAutomatically = true
addSubview(textField)
let textColor: UIColor
switch type {
case .login:
textColor = theme.colorForType(.NormalText)
textField.layer.borderColor = theme.colorForType(.LoginButtonBackground).cgColor
textField.layer.borderWidth = 0.5
textField.layer.masksToBounds = true
textField.layer.cornerRadius = 6.0
case .normal:
textColor = theme.colorForType(.NormalText)
}
titleLabel = UILabel()
titleLabel.textColor = textColor
titleLabel.font = UIFont.systemFont(ofSize: 18.0)
titleLabel.backgroundColor = .clear
addSubview(titleLabel)
hintLabel = UILabel()
hintLabel.textColor = textColor
hintLabel.font = UIFont.antidoteFontWithSize(15.0, weight: .medium)
hintLabel.numberOfLines = 0
hintLabel.backgroundColor = .clear
addSubview(hintLabel)
}
func installConstraints() {
titleLabel.snp.makeConstraints {
$0.top.leading.trailing.equalTo(self)
}
textField.snp.makeConstraints {
$0.top.equalTo(titleLabel.snp.bottom).offset(Constants.VerticalOffset)
$0.leading.trailing.equalTo(self)
$0.height.equalTo(Constants.TextFieldHeight)
}
hintLabel.snp.makeConstraints {
$0.top.equalTo(textField.snp.bottom).offset(Constants.VerticalOffset)
$0.leading.trailing.equalTo(self)
$0.bottom.equalTo(self)
}
}
}