我是Swift 3的初学者,我打算在XCode 8中编写几个自定义控件(IBDesignable)。当我编写自定义文本字段时,我想为它添加正确的占位符。但是,只有当此文本字段没有约束时,才能成功显示正确的占位符。我不知道发生了什么事。
我希望有人可以帮我解决这个问题,非常感谢。
import UIKit
@IBDesignable
class RMLDesignableUITextField: UITextField {
// MARK: PROPERTIES
@IBInspectable var insetX: CGFloat = 0
@IBInspectable var insetY: CGFloat = 0
@IBInspectable var placeholderColor: UIColor = UIColor.white {
didSet {
if let placeholder = self.placeholder {
let attributes = [NSForegroundColorAttributeName: placeholderColor]
attributedPlaceholder = NSAttributedString(string: placeholder, attributes: attributes)
}
}
}
// MARK: Border
var bottomBorder = CALayer()
var rightBorder = CALayer()
var topBorder = CALayer()
var leftBorder = CALayer()
@IBInspectable var showsTopBorder: Bool = false {
didSet {
setupSubviews()
}
}
@IBInspectable var showsBottomBorder: Bool = false {
didSet {
setupSubviews()
}
}
@IBInspectable var showsLeftBorder: Bool = false {
didSet {
setupSubviews()
}
}
@IBInspectable var showsRightBorder: Bool = false {
didSet {
setupSubviews()
}
}
@IBInspectable var borderColor: UIColor = UIColor.clear
@IBInspectable var borderWidth: CGFloat = 0.0 {
didSet {
self.setNeedsDisplay()
}
}
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
@IBInspectable var rightPlaceholder: String = "" {
didSet {
rightPlaceholderLabel.text = rightPlaceholder
}
}
fileprivate var fakePlaceholderLabel: UILabel!
fileprivate var rightPlaceholderLabel: UILabel!
fileprivate var translateX: CGFloat!
{
get {
let attributes = [NSFontAttributeName: font!]
let rightPlaceholderTextSize = rightPlaceholderLabel.text!.size(attributes: attributes)
let rightPlaceholderTextWidth = rightPlaceholderTextSize.width
let translateX = textRect(forBounds: bounds).width - rightPlaceholderTextWidth
return translateX
}
}
// MARK: Initializers
override init(frame: CGRect) {
super.init(frame: frame)
// self.setNeedsDisplay()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
// self.setNeedsDisplay()
fakePlaceholderLabel = UILabel(frame: placeholderRect(forBounds: bounds))
fakePlaceholderLabel.font = font
fakePlaceholderLabel.text = placeholder
fakePlaceholderLabel.textColor = UIColor.lightGray
fakePlaceholderLabel.alpha = 0.0
rightPlaceholderLabel = UILabel(frame: placeholderRect(forBounds: bounds))
rightPlaceholderLabel.font = font
rightPlaceholderLabel.text = rightPlaceholder
rightPlaceholderLabel.textColor = UIColor.lightGray
rightPlaceholderLabel.alpha = 0.0
}
override func layoutSubviews() {
super.layoutSubviews()
addSubview(fakePlaceholderLabel)
addSubview(rightPlaceholderLabel)
setupSubviews()
setNeedsDisplay()
}
}
// MARK: - Lifecycle
extension RMLDesignableUITextField {
override func awakeFromNib() {
super.awakeFromNib()
}
override var intrinsicContentSize : CGSize {
return CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric)
}
override func prepareForInterfaceBuilder() {
//setupSubviews()
}
}
// MARK: - Delegate Methods
extension RMLDesignableUITextField {
// placeholder position
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: insetX, dy: insetY)
}
// text position
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: insetX, dy: insetY)
}
}
// MARK: - UITextField Observing
extension RMLDesignableUITextField {
override internal func willMove(toSuperview newSuperview: UIView!) {
if newSuperview != nil {
NotificationCenter.default.addObserver(self, selector: #selector(RMLDesignableUITextField.didBeginEditing(_:)), name: NSNotification.Name.UITextFieldTextDidBeginEditing, object: self)
NotificationCenter.default.addObserver(self, selector: #selector(RMLDesignableUITextField.didEndEditing(_:)), name: NSNotification.Name.UITextFieldTextDidEndEditing, object: self)
} else {
NotificationCenter.default.removeObserver(self)
}
}
func didBeginEditing(_ notification: Notification) {
placeholder = nil
if notification.object as! RMLDesignableUITextField === self{
UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.4, initialSpringVelocity: 0, options: .curveEaseIn, animations: { () -> Void in
if self.text!.isEmpty {
self.fakePlaceholderLabel.transform = self.fakePlaceholderLabel.transform.translatedBy(x: self.translateX, y: 0.0)
self.fakePlaceholderLabel.alpha = 0.0
self.rightPlaceholderLabel.transform = self.rightPlaceholderLabel.transform.translatedBy(x: self.translateX, y: 0.0)
self.rightPlaceholderLabel.alpha = 1.0
}
}, completion: nil)
}
}
func didEndEditing(_ notification: Notification) {
if notification.object as! RMLDesignableUITextField === self {
UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.4, initialSpringVelocity: 0, options: .curveEaseIn, animations: { () -> Void in
if self.text!.isEmpty {
self.fakePlaceholderLabel.transform = self.fakePlaceholderLabel.transform.translatedBy(x: -self.translateX, y: 0.0)
self.fakePlaceholderLabel.alpha = 1.0
self.rightPlaceholderLabel.transform = self.rightPlaceholderLabel.transform.translatedBy(x: -self.translateX, y: 0.0)
self.rightPlaceholderLabel.alpha = 0.0
}
}, completion: nil)
}
}
}
// MARK: - Methods
extension RMLDesignableUITextField {
fileprivate func pnpAddBorder(_ border: CALayer, color: UIColor, frame: CGRect) {
border.backgroundColor = color.cgColor
border.frame = frame
layer.addSublayer(border)
// layer.masksToBounds = true
}
func pnpAddTopBorder(_ width: CGFloat, color: UIColor = UIColor.black) {
pnpAddBorder(topBorder, color: color, frame: CGRect(x: 0, y: 0, width: frame.width, height: width))
}
func pnpAddBottomBorder(_ width: CGFloat, color: UIColor = UIColor.black) {
pnpAddBorder(bottomBorder, color: color, frame: CGRect(x: 0, y: frame.height - width, width: frame.width, height: width))
}
func pnpAddLeftBorder(_ width: CGFloat, color: UIColor = UIColor.black) {
pnpAddBorder(leftBorder, color: color, frame: CGRect(x: 0, y: 0, width: width, height: frame.height))
}
func pnpAddRightBorder(_ width: CGFloat, color: UIColor = UIColor.black) {
pnpAddBorder(rightBorder, color: color, frame: CGRect(x: frame.width - width, y: 0, width: width, height: frame.height))
}
func setupSubviews() {
// if (showsTopBorder || showsBottomBorder || showsLeftBorder || showsRightBorder) && borderWidth == 0 {
// borderWidth = 1
// }
if showsTopBorder {
pnpAddTopBorder(borderWidth, color: borderColor)
} else {
topBorder.removeFromSuperlayer()
}
if showsBottomBorder {
pnpAddBottomBorder(borderWidth, color: borderColor)
} else {
bottomBorder.removeFromSuperlayer()
}
if showsLeftBorder {
pnpAddLeftBorder(borderWidth, color: borderColor)
} else {
leftBorder.removeFromSuperlayer()
}
if showsRightBorder {
pnpAddRightBorder(borderWidth, color: borderColor)
} else {
rightBorder.removeFromSuperlayer()
}
self.setNeedsDisplay()
}
}