首页 > 解决方案 > 从自定义 @IBDesignable UITextField 类控制占位符文本颜色。斯威夫特 4.2,Xcode 10

问题描述

我创建了 Cocoa Touch 类:

这是 MyTextFieldStyle.swift 文件:

import UIKit

@IBDesignable

class MyTextFieldStyle: UITextField {

@IBInspectable var FavoriteTextColor : UIColor = UIColor.white {
    didSet {
        self.textColor = FavoriteTextColor
    }
}

override func awakeFromNib() {
    super.awakeFromNib()
    self.textColor = self.FavoriteTextColor
}

}

如何添加这 3 个控件,

像上面的“FavoriteTextColor”?(斯威夫特 4.2 和 Xcode 10)

标签: swiftxcodexcode10swift4.2

解决方案


我会做我的IBDesignables不同。我会将我所有的最终作业放在同一个函数中,例如这里是我自己UITextField使用的自定义。

@IBDesignable public class HooopTextfield: UITextField, UITextFieldDelegate {

    @IBInspectable public var fontName: String? = "AvenirNext-Bold" {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var fontSize: CGFloat = 15 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var fontColor: UIColor = UIColor.white {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var customTextAlignment: Int = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var borderColor: UIColor = UIColor.white {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var letterSpacing: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var cornerRadius: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var customPlaceholder: String? = nil {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var horizontalInset: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var verticalInset: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var selfDelegate: Bool = false {
        didSet {
            if selfDelegate {
                self.delegate = self
            }
        }
    }

    @IBInspectable public var borderWidth: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var baseLineOffset: CGFloat = 0 {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var placeholderColor: UIColor? = nil {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var requiredColor: UIColor? = nil {
        didSet {
            decorate()
        }
    }

    @IBInspectable public var requiredCharacter: String = "*"{
        didSet {
            decorate()
        }
    }

    @IBOutlet public var nextField:HooopTextfield?

    /*** more inspectable var can be added **/

    override public func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
    }

    override public func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
    }

    func decorate() {
        // Setup border and corner radius
        self.layer.cornerRadius = cornerRadius
        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.cgColor
        // Setup text style
        let paragraphStyle: NSMutableParagraphStyle = NSMutableParagraphStyle()
        switch customTextAlignment {
        case 2:
            paragraphStyle.alignment = .right
            break
        case 1:
            paragraphStyle.alignment = .center
            break
        default:
            paragraphStyle.alignment = .left
            break
        }
        var titleAttributes:[NSAttributedStringKey : Any] = [
            NSAttributedStringKey.foregroundColor: fontColor,
            NSAttributedStringKey.kern: letterSpacing,
            NSAttributedStringKey.baselineOffset: baseLineOffset,
            NSAttributedStringKey.paragraphStyle: paragraphStyle
        ]
        if let _ = fontName {
            titleAttributes[NSAttributedStringKey.font] = UIFont(name: fontName!, size: fontSize)
        }
        if let _ = customPlaceholder {
            var placeholderAttributes = titleAttributes
            if let _ = placeholderColor {
                placeholderAttributes[NSAttributedStringKey.foregroundColor] = placeholderColor
            }
            let attributedPlaceholder = NSMutableAttributedString(string: customPlaceholder!, attributes: placeholderAttributes)
            if let _ = requiredColor {
                let range = (customPlaceholder! as NSString).range(of: requiredCharacter)
                attributedPlaceholder.addAttribute(NSAttributedStringKey.foregroundColor, value: requiredColor!, range: range)
            }
            self.attributedPlaceholder = attributedPlaceholder
        }
        self.defaultTextAttributes = titleAttributes
    }

    // MARK: - UITexfieldDelegate

    public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if (nextField != nil) {
            nextField?.becomeFirstResponder()
        }
        return true
    }
}

对于占位符,我有基本的东西,如fontColor, fontSize, , 相同的东西。fontName然后我有更多视觉上的东西,比如borderColor, cornerRadius,borderWidth等等。最后我还有一些嵌入的矩形定位来对齐我的故事板中的所有内容。我使用NSMutableAttributedString这些是因为它们是最可定制的,让我也能够为必填字段等着色。

最后,我还有一点@IBOutlet,当与布尔值结合使用时,我还可以使用键盘上的下一个按钮从一个文本字段跳转到下一个文本字段selfDelegate

向我询问您对此有任何疑问并尝试使用它,我认为您应该可以做任何您想做的事情@IBDesignable

编辑1:在我忘记之前,我建议使用decorate或等效功能,因为您应用更改的顺序在大多数情况下都很重要。

编辑2:修复了错误,这很可能是由于迅速改变了如何使用NSAttributedString属性,但奇怪的是,它似乎placeholderAttributes需要,[NSAttributedStringKey: Any]defaultTextAttributes需要[String: Any]不知道为什么会这样。但它现在应该可以工作了。

编辑 3:可能是因为我有不同版本的 Xcode 或者因为它是一个游乐场,我有一条关于 defaultTextAttributes 的消息,但我已经通过删除它来修复它,.rawValue如果它与需要做的相反,知道这NSAttributedStringKey.key.rawValue将是一个字符串你可以NSAttributedStringKey通过使用NSAttributedStringKey.init(rawValue:String)


推荐阅读