我想保持边界在底部的部分只在 UITextField。 但我不知道怎么才能把它保持在底部。
UITextField
你能给我点建议吗?
您可以为底部边框创建一个图像,并将其设置为 UITextField 的背景:
yourTextField.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"yourBorderedImageName"]];
或者将 borderStyle 设置为 none,并将换行图像的长度与 textfield 的长度完全相等!
我正在创建自定义 textField,使其成为 SwiftUI 的可重用组件
textField
SwiftUI
struct CustomTextField: View { var placeHolder: String @Binding var value: String var lineColor: Color var width: CGFloat var body: some View { VStack { TextField(self.placeHolder, text: $value) .padding() .font(.title) Rectangle().frame(height: self.width) .padding(.horizontal, 20).foregroundColor(self.lineColor) } } }
用法:
@Binding var userName: String @Binding var password: String var body: some View { VStack(alignment: .center) { CustomTextField(placeHolder: "Username", value: $userName, lineColor: .white, width: 2) CustomTextField(placeHolder: "Password", value: $password, lineColor: .white, width: 2) } }
Swift 5.0
我在这里使用可视化格式化语言(VFL) ,这将允许添加一行到任何 UIControl。
UIControl
您可以创建类似于 UIView+Extention.swift的 UIView扩展类
UIView+Extention.swift
UIView
import UIKit enum LinePosition { case top case bottom } extension UIView { func addLine(position: LinePosition, color: UIColor, width: Double) { let lineView = UIView() lineView.backgroundColor = color lineView.translatesAutoresizingMaskIntoConstraints = false // This is important! self.addSubview(lineView) let metrics = ["width" : NSNumber(value: width)] let views = ["lineView" : lineView] self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[lineView]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) switch position { case .top: self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[lineView(width)]", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) break case .bottom: self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lineView(width)]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) break } } }
textField.addLine(position: .LINE_POSITION_BOTTOM, color: .darkGray, width: 0.5)
目标丙:
您可以将这个 helper 方法添加到您的全局 helper 类(我使用的是全局 class 方法)或同一个视图控制器(使用实例方法)中。
typedef enum : NSUInteger { LINE_POSITION_TOP, LINE_POSITION_BOTTOM } LINE_POSITION; - (void) addLine:(UIView *)view atPosition:(LINE_POSITION)position withColor:(UIColor *)color lineWitdh:(CGFloat)width { // Add line UIView *lineView = [[UIView alloc] init]; [lineView setBackgroundColor:color]; [lineView setTranslatesAutoresizingMaskIntoConstraints:NO]; [view addSubview:lineView]; NSDictionary *metrics = @{@"width" : [NSNumber numberWithFloat:width]}; NSDictionary *views = @{@"lineView" : lineView}; [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[lineView]|" options: 0 metrics:metrics views:views]]; switch (position) { case LINE_POSITION_TOP: [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[lineView(width)]" options: 0 metrics:metrics views:views]]; break; case LINE_POSITION_BOTTOM: [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lineView(width)]|" options: 0 metrics:metrics views:views]]; break; default: break; } }
[self addLine:self.textField atPosition:LINE_POSITION_TOP withColor:[UIColor darkGrayColor] lineWitdh:0.5];
Xamarin 代码:
var border = new CALayer(); nfloat width = 2; border.BorderColor = UIColor.Black.CGColor; border.Frame = new CoreGraphics.CGRect(0, textField.Frame.Size.Height - width, textField.Frame.Size.Width, textField.Frame.Size.Height); border.BorderWidth = width; textField.Layer.AddSublayer(border); textField.Layer.MasksToBounds = true;
目标 C
[txt.layer setBackgroundColor: [[UIColor whiteColor] CGColor]]; [txt.layer setBorderColor: [[UIColor grayColor] CGColor]]; [txt.layer setBorderWidth: 0.0]; [txt.layer setCornerRadius:12.0f]; [txt.layer setMasksToBounds:NO]; [txt.layer setShadowRadius:2.0f]; txt.layer.shadowColor = [[UIColor blackColor] CGColor]; txt.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); txt.layer.shadowOpacity = 1.0f; txt.layer.shadowRadius = 1.0f;
斯威夫特
txt.layer.backgroundColor = UIColor.white.cgColor txt.layer.borderColor = UIColor.gray.cgColor txt.layer.borderWidth = 0.0 txt.layer.cornerRadius = 5 txt.layer.masksToBounds = false txt.layer.shadowRadius = 2.0 txt.layer.shadowColor = UIColor.black.cgColor txt.layer.shadowOffset = CGSize.init(width: 1.0, height: 1.0) txt.layer.shadowOpacity = 1.0 txt.layer.shadowRadius = 1.0
extension UITextField { func setBottomBorder(color:String) { self.borderStyle = UITextBorderStyle.None let border = CALayer() let width = CGFloat(1.0) border.borderColor = UIColor(hexString: color)!.cgColor border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) border.borderWidth = width self.layer.addSublayer(border) self.layer.masksToBounds = true } }
然后这样做:
yourTextField.setBottomBorder(color: "#3EFE46")
您可以创建 UITextField的子类,如下所示:
class TextField : UITextField { override var tintColor: UIColor! { didSet { setNeedsDisplay() } } override func draw(_ rect: CGRect) { let startingPoint = CGPoint(x: rect.minX, y: rect.maxY) let endingPoint = CGPoint(x: rect.maxX, y: rect.maxY) let path = UIBezierPath() path.move(to: startingPoint) path.addLine(to: endingPoint) path.lineWidth = 2.0 tintColor.setStroke() path.stroke() } }
我所做的是为 UITextField 创建一个扩展,并添加了 Designer 可编辑属性。将此属性设置为任何颜色都会将边框(底部)更改为该颜色(将其他边框设置为无)。
由于这也需要改变占位符的文本颜色,我也添加到扩展。
extension UITextField { @IBInspectable var placeHolderColor: UIColor? { get { return self.placeHolderColor } set { self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSForegroundColorAttributeName: newValue!]) } } @IBInspectable var bottomBorderColor: UIColor? { get { return self.bottomBorderColor } set { self.borderStyle = UITextBorderStyle.None; let border = CALayer() let width = CGFloat(0.5) border.borderColor = newValue?.CGColor border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) border.borderWidth = width self.layer.addSublayer(border) self.layer.masksToBounds = true } } }
您可以在类之外创建这个扩展,并用任意 borderWidth 替换 width。
Swift 4
extension UITextField { func setBottomBorder(withColor color: UIColor) { self.borderStyle = UITextBorderStyle.none self.backgroundColor = UIColor.clear let width: CGFloat = 1.0 let borderLine = UIView(frame: CGRect(x: 0, y: self.frame.height - width, width: self.frame.width, height: width)) borderLine.backgroundColor = color self.addSubview(borderLine) } }
原创的
extension UITextField { func setBottomBorder(borderColor: UIColor) { self.borderStyle = UITextBorderStyle.None self.backgroundColor = UIColor.clearColor() let width = 1.0 let borderLine = UIView(frame: CGRectMake(0, self.frame.height - width, self.frame.width, width)) borderLine.backgroundColor = borderColor self.addSubview(borderLine) } }
然后将其添加到 viewDidLoad 中,用 UITextField 变量替换 yourTextField,并在边框中使用任意颜色
yourTextField.setBottomBorder(UIColor.blackColor())
这基本上是在文本字段的底部添加一个具有该颜色的视图。
在 Swift 3上。您可以创建一个扩展并在视图类后面添加。
extension UITextField { func setBottomBorder(borderColor: UIColor) { self.borderStyle = UITextBorderStyle.none self.backgroundColor = UIColor.clear let width = 1.0 let borderLine = UIView() borderLine.frame = CGRect(x: 0, y: Double(self.frame.height) - width, width: Double(self.frame.width), height: width) borderLine.backgroundColor = borderColor self.addSubview(borderLine) } }
如果你想先做 在不知道框架的情况下,没有子类化和 没有自动输出:
Swift 5 /斯威夫特4. x/< strong > Swift 3. x
extension UITextField { func setBottomBorder() { self.borderStyle = .none self.layer.backgroundColor = UIColor.white.cgColor self.layer.masksToBounds = false self.layer.shadowColor = UIColor.gray.cgColor self.layer.shadowOffset = CGSize(width: 0.0, height: 1.0) self.layer.shadowOpacity = 1.0 self.layer.shadowRadius = 0.0 } }
从任何地方调用为 yourTextField.setBottomBorder()而不确定帧是否正确。
yourTextField.setBottomBorder()
结果如下:
快速用户界面
struct MyTextField: View { var myPlaceHolder: String @Binding var text: String var underColor: Color var height: CGFloat var body: some View { VStack { TextField(self.myPlaceHolder, text: $text) .padding() .font(.title) Rectangle().frame(height: self.height) .padding(.horizontal, 24).foregroundColor(self.underColor) } } }
你可以使用这个 有组织的,也可以进一步使用这个 定制扩展:
出现中的“ 一线实施”(以便帧大小正确) :
// Add layer in your textfield yourTextField.addLayer(.bottom).addPadding(.left) // Extension extension UITextField { enum Position { case up, bottom, right, left } // MARK: - Add Single Line Layer func addLayer(_ position: Position) -> UITextField { // bottom layer let bottomLayer = CALayer() // set width let height = CGFloat(1.0) bottomLayer.borderWidth = height // set color bottomLayer.borderColor = UIColor.white.cgColor // set frame // y position changes according to the position let yOrigin = position == .up ? 0.0 : frame.size.height - height bottomLayer.frame = CGRect.init(x: 0, y: yOrigin, width: frame.size.width, height: height) layer.addSublayer(bottomLayer) layer.masksToBounds = true return self } // Add right/left padding view in textfield func addPadding(_ position: Position, withImage image: UIImage? = nil) { let paddingHeight = frame.size.height let paddingViewFrame = CGRect.init(x: 0.0, y: 0.0, width: paddingHeight * 0.6, height: paddingHeight) let paddingImageView = UIImageView.init(frame: paddingViewFrame) paddingImageView.contentMode = .scaleAspectFit if let paddingImage = image { paddingImageView.image = paddingImage } // Add Left/Right view mode switch position { case .left: leftView = paddingImageView leftViewMode = .always case .right: rightView = paddingImageView rightViewMode = .always default: break } } }
下面是@IBChectable 的 Swift 3代码
创建一个新文件可可触摸类快速文件
import UIKit extension UIView { @IBInspectable var cornerRadius: CGFloat { get { return layer.cornerRadius } set { layer.cornerRadius = newValue layer.masksToBounds = newValue > 0 } } @IBInspectable var borderWidth: CGFloat { get { return layer.borderWidth } set { layer.borderWidth = newValue } } @IBInspectable var borderColor: UIColor? { get { return UIColor(cgColor: layer.borderColor!) } set { layer.borderColor = newValue?.cgColor } } @IBInspectable var leftBorderWidth: CGFloat { get { return 0.0 // Just to satisfy property } set { let line = UIView(frame: CGRect(x: 0.0, y: 0.0, width: newValue, height: bounds.height)) line.translatesAutoresizingMaskIntoConstraints = false line.backgroundColor = UIColor(cgColor: layer.borderColor!) line.tag = 110 self.addSubview(line) let views = ["line": line] let metrics = ["lineWidth": newValue] addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line(==lineWidth)]", options: [], metrics: metrics, views: views)) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line]|", options: [], metrics: nil, views: views)) } } @IBInspectable var topBorderWidth: CGFloat { get { return 0.0 // Just to satisfy property } set { let line = UIView(frame: CGRect(x: 0.0, y: 0.0, width: bounds.width, height: newValue)) line.translatesAutoresizingMaskIntoConstraints = false line.backgroundColor = borderColor line.tag = 110 self.addSubview(line) let views = ["line": line] let metrics = ["lineWidth": newValue] addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line]|", options: [], metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line(==lineWidth)]", options: [], metrics: metrics, views: views)) } } @IBInspectable var rightBorderWidth: CGFloat { get { return 0.0 // Just to satisfy property } set { let line = UIView(frame: CGRect(x: bounds.width, y: 0.0, width: newValue, height: bounds.height)) line.translatesAutoresizingMaskIntoConstraints = false line.backgroundColor = borderColor line.tag = 110 self.addSubview(line) let views = ["line": line] let metrics = ["lineWidth": newValue] addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "[line(==lineWidth)]|", options: [], metrics: metrics, views: views)) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line]|", options: [], metrics: nil, views: views)) } } @IBInspectable var bottomBorderWidth: CGFloat { get { return 0.0 // Just to satisfy property } set { let line = UIView(frame: CGRect(x: 0.0, y: bounds.height, width: bounds.width, height: newValue)) line.translatesAutoresizingMaskIntoConstraints = false line.backgroundColor = borderColor line.tag = 110 self.addSubview(line) let views = ["line": line] let metrics = ["lineWidth": newValue] addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line]|", options: [], metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[line(==lineWidth)]|", options: [], metrics: metrics, views: views)) } } func removeborder() { for view in self.subviews { if view.tag == 110 { view.removeFromSuperview() } } }
}
并用下面的代码替换该文件,您将在故事板属性检查器中得到这样的选项
享受:)
这些解决方案都没有真正达到我的期望。我想 子类的文本字段,因为我不想设置边界手动所有的时间。我也想 更改边框颜色例如一个错误。这是我对 Anchors的解决方案:
Anchors
class CustomTextField: UITextField { var bottomBorder = UIView() override func awakeFromNib() { // Setup Bottom-Border self.translatesAutoresizingMaskIntoConstraints = false bottomBorder = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1) // Set Border-Color bottomBorder.translatesAutoresizingMaskIntoConstraints = false addSubview(bottomBorder) bottomBorder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true bottomBorder.leftAnchor.constraint(equalTo: leftAnchor).isActive = true bottomBorder.rightAnchor.constraint(equalTo: rightAnchor).isActive = true bottomBorder.heightAnchor.constraint(equalToConstant: 1).isActive = true // Set Border-Strength } }
——可选——
为了改变颜色,在 CustomTextField Class上加上这样的东西:
CustomTextField Class
@IBInspectable var hasError: Bool = false { didSet { if (hasError) { bottomBorder.backgroundColor = UIColor.red } else { bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1) } } }
并在创建 CustomTextField 实例后触发 Error 调用此
textField.hasError = !textField.hasError
希望这对某人有所帮助;)
这里 myTF 是 MT 文本字段的出口
let border = CALayer() let width = CGFloat(2.0) border.borderColor = UIColor.darkGray.cgColor border.frame = CGRect(x: 0, y: self.myTF.frame.size.height - width, width: self.myTF.frame.size.width, height: self.myTF.frame.size.height) border.borderWidth = width self.myTF.layer.addSublayer(border) self.myTF.layer.masksToBounds = true
import UIkit extension UITextField { func underlinedLogin() { let border = CALayer() let width = CGFloat(1.0) border.borderColor = UIColor.black.cgColor border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) border.borderWidth = width self.layer.addSublayer(border) self.layer.masksToBounds = true }
视图加载调用方法
mobileNumberTextField.underlinedLogin()
passwordTextField.underlinedLogin()
//在主故事板上选择 like text field
供查看: (最受推荐) 它适用于使用 UIView extension的所有类型的 UIView子类(视图、文本文件、标签等)
UIView extension
它更简单和方便。但唯一的条件是 view必须包含一个自动布局。
view
extension UIView { enum Line_Position { case top case bottom } func addLine(position : Line_Position, color: UIColor, height: Double) { let lineView = UIView() lineView.backgroundColor = color lineView.translatesAutoresizingMaskIntoConstraints = false // This is important! self.addSubview(lineView) let metrics = ["width" : NSNumber(value: height)] let views = ["lineView" : lineView] self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[lineView]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) switch position { case .top: self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[lineView(width)]", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) break case .bottom: self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lineView(width)]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views)) break } } }
怎么用?
// UILabel self.lblDescription.addLine(position: .bottom, color: UIColor.blue, height: 1.0)
还有
// UITextField self.txtArea.addLine(position: .bottom, color: UIColor.red, height: 1.0)
更新密码:
extension UITextField { func addUnderline() { let layer = CALayer() layer.backgroundColor = #colorLiteral(red: 0.6666666865, green: 0.6666666865, blue: 0.6666666865, alpha: 1) layer.frame = CGRect(x: 0.0, y: self.frame.size.height - 1.0, width: self.frame.size.width, height: 1.0) self.clipsToBounds = true self.layer.addSublayer(layer) self.setNeedsDisplay()} }
现在在 视图()中调用这个函数
override func viewDidLayoutSubviews() { textField.addUnderline() }
注意: 此方法只能在 < strong > viewDidLayoutSubviews ()中工作
我已经研究了这些解决方案中的每一个,它们似乎也适用于一个问题。黑暗模式和背景设置
UITextField的背景设置必须与父视图的背景匹配,否则将不显示任何行
这个可以在光照模式下工作 要在黑暗模式下工作,将背景颜色改为黑色即可 排除背面颜色和线条不会出现
let field = UITextField() field.backgroundColor = UIColor.white field.bottomBorderColor = UIColor.red
这对我来说是最好的解决办法
extension UITextField { func addPadding() { let paddingView = UIView(frame: CGRect(x:0, y:0, width: 10, height: self.frame.height)) self.leftView = paddingView self.leftViewMode = .always } @IBInspectable var placeHolderColor: UIColor? { get { return self.placeHolderColor } set { self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: newValue!]) } } @IBInspectable var bottomBorderColor: UIColor? { get { return self.bottomBorderColor } set { self.borderStyle = .none self.layer.masksToBounds = false self.layer.shadowColor = newValue?.cgColor self.layer.shadowOffset = CGSize(width: 0.0, height: 1.0) self.layer.shadowOpacity = 1.0 self.layer.shadowRadius = 0.0 } } }
let border = CALayer() let lineWidth = CGFloat(0.3) border.borderColor = UIColor.lightGray.cgColor border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - lineWidth, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height) border.borderWidth = lineWidth emailTextField.layer.addSublayer(border) emailTextField.layer.masksToBounds = true
教程
在 SwiftUI 中,有一个名为 Divider的 View与此完全匹配。您可以通过将它们嵌入到一个简单的 VStack中,将其添加到任何视图的下面:
Divider
View
VStack
VStack { Text("This could be any View") Divider() }
在 SwiftUI 中,最简单的实现是,
struct MyTextField: View { var myPlaceHolder: String @Binding var text: String var underColor: Color var height: CGFloat var body: some View { VStack { TextField(self.myPlaceHolder, text: $text) .padding(.horizontal, 24) .font(.title) Rectangle().frame(height: self.height) .padding(.horizontal, 24).foregroundColor(self.underColor) } } }
MyTextField(myPlaceHolder: "PlaceHolder", text: self.$text, underColor: .red, height: 3)