我正在开发一个可定制的UITextField(见下面的代码)。我在底部添加了一个边框(您可以在情节提要中设置它)。但是,我在设置这个边界所包含的CALayer框架时遇到了问题。
如果我在didSet方法中设置它,它不会出现在屏幕上。我认为这是因为(UITextField的)帧尚未计算(可能var showBottomBorder在此之前被调用)。
所以我把它移到了didSet方法(见下面的代码)。这很管用。
但现在我有另一个问题。我真的不能再改变那个框架了。每次我改变它,它都会被layoutSubviews()重置,我想这就是所谓的。
在我的代码的底部,有一个方法layoutSubviews()。在那里,我想移动我的底部边界(动画)。但没用。边界哪儿也不动。就像我说的,我认为这是因为我在textFieldDidBeginEditing方法中设置了框架。
有没有更好的方法来设置底部边框的边框?能让我换东西的方法?

@IBDesignable
class CustomizableTextField: UITextField, UITextFieldDelegate {

    // MARK: - Properties
    private var bottomBorder = CALayer()

    // MARK: - @IBInspectables
    @IBInspectable var roundCorners: CGFloat = 0 {
        didSet {
            self.layer.cornerRadius = roundCorners
            self.clipsToBounds = true
        }
    }

    /** -- */
    @IBInspectable var borderWidth: CGFloat = 1.0 {
        didSet {
            self.layer.borderWidth = self.borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor = UIColor.white {
        didSet {
            self.layer.borderColor = self.borderColor.cgColor
        }
    }
    /** -- */

    /** -- */
    private var showBottomBorder: Bool = false {
        didSet {
            switch showBottomBorder {
            case true:
                bottomBorder.borderColor = self.bottomBorderColor.cgColor
                bottomBorder.borderWidth = self.bottomBorderWidth

                self.layer.addSublayer(bottomBorder)
                self.layer.masksToBounds = true
                break
            case false:
                bottomBorder.removeFromSuperlayer()
                break
            }
        }
    }
    @IBInspectable var bottomBorderWidth: CGFloat = 1.0 {
        didSet {
            self.showBottomBorder = false
            self.showBottomBorder = true
        }
    }
    @IBInspectable var bottomBorderColor: UIColor = UIColor.white {
        didSet {
            self.showBottomBorder = false
            self.showBottomBorder = true
        }
    }
    /** -- */

    /** -- */
    // Somwhow, the default panel for my font color doesn't change anything, so I created this
    @IBInspectable var fixedFontColor: UIColor = UIColor.white {
        didSet {
            self.textColor = fixedFontColor
        }
    }
    @IBInspectable var placeholderFontColor: UIColor = UIColor.white {
        didSet {
            var placeholderTxt = ""
            if let txt = self.placeholder {
                placeholderTxt = txt
            }

            self.attributedPlaceholder = NSAttributedString(string: placeholderTxt, attributes: [NSForegroundColorAttributeName: placeholderFontColor])
        }
    }
    /** -- */

    // MARK: - Overrides and Initializers
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        // HERE
        bottomBorder.frame = CGRect(x: 0, y: self.frame.size.height - self.bottomBorderWidth, width:  self.frame.size.width, height: self.frame.size.height)
    }

    // setting the textField delegate to self
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        //self.borderStyle = .none
        self.delegate = self
    }

    // MARK: - Events
    func textFieldDidBeginEditing(_ textField: UITextField) {

    }

最佳答案

您可以在uitextfield上使用和扩展设置边框。
并用KVC保存对它的引用。
通过重写LayOutSubVIEW,每个布局都会改变,我们检查边界是否存在,如果是这样,删除它,并用新的框架重新创建一个新的框架:

import UIKit

let MyTopBorder = "myTopBorder"
let MyBottomBorder = "myBottomBorder"
struct Defaults {
    static let width = CGFloat(1.0)
    static func bottonBorderFrame(view: UIView)->CGRect {
     return CGRect(x: CGFloat(0), y: view.frame.size.height - Defaults.width,   width:  view.frame.size.width, height: view.frame.size.height)
    }
    static func topBorderFrame(view: UIView)->CGRect {
        return CGRect(x: CGFloat(0), y: CGFloat(0) ,   width:  view.frame.size.width, height: Defaults.width)
    }
}

extension UITextField
{
    func setBottomBorder(color:CGColor)
    {
        if let isBottomBorder = self.getBottomBorderIfExists() {
            isBottomBorder.removeFromSuperlayer()
        }
        self.setBorderWithFrame(Defaults.bottonBorderFrame(self), color: color, andKey: MyBottomBorder)
    }

    func setTopBorder(color:CGColor)
    {
        if let isTopBorder = self.getTopBorderIfExists() {
            isTopBorder.removeFromSuperlayer()
        }
        self.setBorderWithFrame(Defaults.topBorderFrame(self), color: color, andKey: MyTopBorder)
    }

    func setBorderWithFrame(frame: CGRect, color: CGColor, andKey: String) {
        self.borderStyle = UITextBorderStyle.None;
        let border = CALayer()
        border.borderColor = color
        border.frame = frame
        border.borderWidth = Defaults.width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
        self.layer.setValue(border, forKey: andKey)
    }

    func removeTopBorder() {
        if let isTopBorder = self.getTopBorderIfExists() {
            self.layer.setValue(nil, forKey: MyTopBorder)
            isTopBorder.removeFromSuperlayer()
        }
    }

    func removeBottomBorder() {
        if let isBottomBorder = self.getBottomBorderIfExists() {
            self.layer.setValue(nil, forKey: MyBottomBorder)
            isBottomBorder.removeFromSuperlayer()
        }
    }

    private func getBorderIfExistsByKey(key: String)->CALayer? {
        if let isBorderSet = self.layer.valueForKey(key) {
            if let borderIsCALayer = isBorderSet as? CALayer {
                return borderIsCALayer
            }
        }
        return nil
    }

    private func getTopBorderIfExists()->CALayer? {
        return self.getBorderIfExistsByKey(MyTopBorder)
    }

    private func getBottomBorderIfExists()->CALayer? {
        return self.getBorderIfExistsByKey(MyBottomBorder)
    }

    public override func layoutSubviews() {
        super.layoutSubviews()

        // Update bottom on frame change
        if let isBottomBorder = self.getBottomBorderIfExists() {
            let borderColor = isBottomBorder .borderColor
            self.removeBottomBorder()
            self.setBottomBorder(borderColor!)
        }
        // Update top on frame change
        if let isTopBorder = self.getTopBorderIfExists() {
            let borderColor = isTopBorder.borderColor
            self.removeTopBorder()
            self.setTopBorder(borderColor!)
        }
    }
}

用法:
  let textField = UITextField(frame: CGRect(x: 100,y: 100, width: 100, height: 100))
        textField.backgroundColor = UIColor.blueColor() // Thie color is for visulizing better
        self.view.addSubview(textField)
        textField.setBottomBorder(UIColor.blackColor().CGColor) // Now you have a border
        textField.frame = CGRect(x: 150, y: 200, width: 200, height: 200) // And the border updated to the new frame
        // Now if you would like to change from bottom to top, simply do this:
        textField.removeBottomBorder()
        textField.setTopBorder(UIColor.blackColor().CGColor)

10-07 19:16
查看更多