(Swift) 自定義UITextField

自定義UITextField,支持placeholderFont、placeholderColor、offset、isEnableDecimalLimit

  • 使用方法
lazy var textField = TextField()
view.addSubview(textField)
textField.frame = CGRect(x: 0, y: 0, width: 400, height: 60)
textField.center = view.center
textField.placeholder = "請輸入內容..."
textField.placeholderFont = .systemFont(ofSize: 20)
textField.placeholderColor = .red
textField.isEnableDecimalLimit = true
textField.offset = CGPoint(x: 10, y: 10)
textField.font = .systemFont(ofSize: 30)
textField.backgroundColor = .lightGray
textField.keyboardType = .decimalPad
  • 源碼分享
class TextField: UITextField {
    /// 占位字體
    var placeholderFont: UIFont? {
        willSet {
            if let label = value(forKey: "placeholderLabel") as? UILabel {
                label.font = newValue
            }
        }
    }
    
    /// 占位顏色
    var placeholderColor: UIColor? {
        willSet {
            if let label = value(forKey: "placeholderLabel") as? UILabel {
                label.textColor = newValue
            }
        }
    }
    
    /// 內邊距偏移量
    var offset: CGPoint = .zero
    
    /// 是否啟用小數(shù)點后僅允許兩位的輸入限制
    var isEnableDecimalLimit: Bool = false
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        delegate = self
    }
}

extension TextField {
    /// 占位符偏移量
    override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
        if let leftView {
            return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - leftView.bounds.width - offset.x, height: bounds.height)), leftView.bounds.width + offset.x, offset.y)
        }
        return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - offset.x, height: bounds.height)), offset.x, offset.y)
    }
    
    /// 文本最終顯示偏移量
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        if let leftView {
            return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - leftView.bounds.width - offset.x, height: bounds.height)), leftView.bounds.width + offset.x, offset.y)
        }
        return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - offset.x, height: bounds.height)), offset.x, offset.y)
    }
    
    /// 文本編輯時偏移量
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        if let leftView {
            return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - leftView.bounds.width - offset.x, height: bounds.height)), leftView.bounds.width + offset.x, offset.y)
        }
        return CGRectOffset(CGRect(origin: bounds.origin, size: CGSize(width: bounds.width - offset.x, height: bounds.height)), offset.x, offset.y)
    }
}

extension TextField: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard isEnableDecimalLimit else { return true }
        
        // 獲取當前文本
        let currentText = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) ?? ""
        
        // 正則表達式
        let regex = "^$|^0$|^0\\.[0-9]{0,2}$|^[1-9][0-9]*\\.?[0-9]{0,2}$"
        
        // 創(chuàng)建正則表達式對象
        let expression = try? NSRegularExpression(pattern: regex, options: [])
        
        // 校驗當前文本是否符合正則表達式
        if let _ = expression?.firstMatch(in: currentText, options: [], range: NSRange(location: 0, length: currentText.utf16.count)) {
            return true
        }
        
        // 若不符合正則表達式,則不允許更改
        return false
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。