【问题标题】:Unable to remove a CALayer from UITextField无法从 UITextField 中删除 CALayer
【发布时间】:2020-06-09 19:40:56
【问题描述】:

所以,我有这个自定义 UITextField,我有两种方法可以添加 CALayer 和删除 CALayer,但删除不起作用。

@IBDesignable class AppTextField : UITextField {

    private let bottomLine = CALayer()

    override func layoutSubviews() {
        self.font = .systemFont(ofSize: 20)
        self.addBottomLine()
        self.clearButtonMode = .unlessEditing
        super.layoutSubviews()
    }

    func removeBttomLine() {
        bottomLine.removeFromSuperlayer()
    }

    private func addBottomLine() {
        bottomLine.frame = CGRect(origin: CGPoint(x: 0, y: self.frame.height + 4), size: CGSize(width: self.frame.width, height: 1))
        bottomLine.backgroundColor = UIColor.init(hexString: "#DCCFCA")?.cgColor
        self.borderStyle = .none
        self.layer.addSublayer(bottomLine)
    }
}

【问题讨论】:

  • 你在哪里打电话removeBttomLine()
  • @DonMag 在我的viewController.
  • 你是否在开头显示红线?然后在该字段成为第一响应者时将其删除?或者不显示它直到它成为第一响应者?
  • @DonMag 我不确定!我正在尝试从我的ViewControllerViewDidLoad 中删除它。

标签: ios swift calayer


【解决方案1】:

您在layoutSubviews() 中唯一应该做的就是根据需要更新框架。

这将在字段被编辑时显示红线,并在字段IS被编辑时将其移除:

@IBDesignable class AppTextField : UITextField {

    private let bottomLine = CALayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        self.font = .systemFont(ofSize: 20)
        self.backgroundColor = .white
        self.clearButtonMode = .unlessEditing
        self.borderStyle = .none
        bottomLine.backgroundColor = UIColor.red.cgColor
        addBottomLine()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        var r = bounds
        r.origin.y = bounds.maxY
        r.size.height = 4.0
        bottomLine.frame = r
    }

    func removeBottomLine() {
        bottomLine.removeFromSuperlayer()
    }
    private func addBottomLine() {
        self.layer.addSublayer(bottomLine)
    }

    override func resignFirstResponder() -> Bool {
        super.resignFirstResponder()
        addBottomLine()
        return true
    }
    override func becomeFirstResponder() -> Bool {
        super.becomeFirstResponder()
        removeBottomLine()
        return true
    }
}

【讨论】:

  • 感谢您的解释! :)
【解决方案2】:

原因可能是因为layoutSubviews 方法被多次调用并且层被多次添加。如果您正在使用情节提要,请尝试将 addBottomLine 方法移动到 required init?(coder:) 方法或使用 init(frame:) 或自定义 init ,无论哪个只被调用一次。这是一个例子:

@IBDesignable class AppTextField : UITextField {

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        addBottomLine()
    }
}

【讨论】:

    【解决方案3】:

    您在 add 方法中做了 3 件事:

    1. 调节框架
    2. 设置颜色
    3. 添加为子层

    而且因为您是从 layoutSubviews 调用它,所以它被多次调用并且您以添加了多个层结束,这就是调用 remove 似乎不起作用的原因。
    要使此代码正常工作,您应该将添加部分移至 init(withCoderwithFrame 或两者)。您可以通过设置颜色加入它,因为它可以完成一次。下一部分是在layoutSubviews 中调整框架,这是必需的,因为图层不能进入自动布局。最后,您将创建,添加为子层并在初始化时调用一次设置部分,并在布局过程中多次调用调整。现在在调用一次时删除 - 这次它会产生可见的效果。

    【讨论】:

    • 感谢您的解释!
    猜你喜欢
    • 2013-04-19
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多