This is about iOS 17 only. The only way I could hack around and achieve something like this was
so
///True™ iOS look of the border, and you can change the color
class FixedUITextField: UITextField {
var completed: Bool = true {
didSet {
fakeLayer.borderColor = completed ? rememberDefaultColor : UIColor.red.cgColor
}
}
private var rememberDefaultColor: CGColor? = UIColor.gray.cgColor
private lazy var fakeLayer: CALayer = {
let v = RepairedCALayer()
for found in layer.sublayers ?? [] {
if found.borderWidth > 0 {
layer.insertSublayer(v, above: found)
v.backgroundColor = found.backgroundColor
v.borderColor = found.borderColor
v.borderWidth = found.borderWidth
v.cornerRadius = found.cornerRadius
v.cornerCurve = found.cornerCurve
print("found and covered")
rememberDefaultColor = found.borderColor
return v
}
}
// defaults ICO disaster
v.backgroundColor = UIColor.systemBackground.cgColor
v.borderColor = UIColor.blue.cgColor
v.borderWidth = 1.0 / UIScreen.main.scale
v.cornerRadius = 4.0
v.cornerCurve = .circular
layer.addSublayer(v)
return v
}()
override func layoutSubviews() {
super.layoutSubviews()
fakeLayer.frame = bounds
}
}
This is about iOS 17 only. Am I missing something really obvious?
This is about iOS 17 only. Even more issues on this time waste ...
Am I missing something really obvious? - is there a way to change the border color of a UITextField as is?
It looks like if you set the border style on a UITextField these days,
override func common() {
super.common()
borderStyle = .roundedRect
layer.borderWidth = 1.0 / UIScreen.main.scale
layer.cornerCurve = .circular
layer.cornerRadius = 10
It just adds that to the standard border.
seen here
(tap for large)
If there was a way to turn off the mystery layer (or draw
?), that would be a work around, but I just cannot find a way to turn it off. (If you hide it, "they" turn it on again after a few frames! I don't know how to examine the source code to see what's going on.)
If you're investigating this recall that is it begins from storyboard they set borderStyle = .roundedRect
(it's .none
if you just instantiate a text field), adding further confusion.
In iOS17 UIKit is there really ANY way at all to changethe border color of an iOS17 UITextField?
No.
You have two and a half possibilities:
Use the mangle I give in the question, which will exactly copy their border and cover it with an exact match, which you can color as wished. (However, if UIKit changes any quality during the running of an app {eg for an animation, state change, etc} you won't know about that and the look will change.)
Very simply eliminate "their" border and use your own. The only trick to doing so is that you have to set the text rect (which is essentially setting the padding visually):
///Essentially, you can't CHANGE THE COLOR of the border in a UITextField.
///Here, we simply turn it off and recreate it strictly BY EYE.
///Don't expect this to match UITextField in any serious project.
class ManualBorderUIITextField: UIITextField {
override func common() {
super.common()
borderStyle = .none
layer.borderWidth = 2.0 / UIScreen.main.scale
// In 2024 iOS it's 1 pixel there, I like 2
layer.cornerCurve = .circular
layer.cornerRadius = 4
layer.borderColor = UIColor.green.cgColor
// Choice is yours. In most real projects you'd be changing it per your use/states etc
}
///Note that very confusingly UITextField will do the intrinsic size for you backwards from this, you don't have to.
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: 7.0, dy: 8.0)
// When you kill the border style this padding becomes zero so you have to do it manually
// In 2024 iOS it's possibly ~7/~6 there but hard to say exactly
}
}
2.5. I guess if you are incredibly anal you could do "1" when you launch a text field, memorize all the values, and then use that in a "2" approach. (Again though, you wouldn't know about any changes "they" might make in theory during the run; you're very simply building a custom control like any other custom control :/ )