我正在开发一个可自定义的UITextField(参见下面的代码)。我在底部添加了一个边框(您可以在故事板中设置它)。但是,我在设置此边框包含的CALayer框架时遇到了问题。
如果我在var showBottomBorder
的{{1}}方法中设置它,它就不会出现在屏幕上。我认为这是因为尚未计算(UITextField的)框架(在此之前可能会调用didSet
)。
所以我把它移到layoutSubviews()
方法(见下面的代码)。这非常有效。
但现在我有另一个问题。我不能再真正改变那个框架了。每当我更改它时,它都会被layoutSubviews()
重置,我认为这是{。}}。
在我的代码底部,有方法textFieldDidBeginEditing
。在那里,我想向上移动我的底部边框(动画)。但它不起作用。边界不会移动到任何地方。就像我说的那样,我认为这是因为我在layoutSubviews()
方法中设置了框架。
有没有更好的方法来设置底部边框的框架?一种允许我改变东西的方法吗?
@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) {
}
答案 0 :(得分:1)
您可以在UITextFiled上使用扩展程序来设置边框。
并使用 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)