在 SwiftUI/Swift/Objective-C/Xamarin 中向 UI TextField 视图添加底部边框线

我想保持边界在底部的部分只在 UITextField。 但我不知道怎么才能把它保持在底部。

你能给我点建议吗?

149398 次浏览

您可以为底部边框创建一个图像,并将其设置为 UITextField 的背景:

 yourTextField.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"yourBorderedImageName"]];

或者将 borderStyle 设置为 none,并将换行图像的长度与 textfield 的长度完全相等!

我正在创建自定义 textField,使其成为 SwiftUI 的可重用组件

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

您可以创建类似于 UIView+Extention.swiftUIView扩展类

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;

enter image description here

目标 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()而不确定帧是否正确。

结果如下:

sample

快速用户界面

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()
}


}
}

}

并用下面的代码替换该文件,您将在故事板属性检查器中得到这样的选项

enter image description here

享受:)

这些解决方案都没有真正达到我的期望。我想 子类的文本字段,因为我不想设置边界手动所有的时间。我也想 更改边框颜色例如一个错误。这是我对 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上加上这样的东西:

@IBInspectable var hasError: Bool = false {
didSet {


if (hasError) {


bottomBorder.backgroundColor = UIColor.red


} else {


bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)


}


}
}

并在创建 CustomTextField 实例后触发 Error 调用此

textField.hasError = !textField.hasError

enter image description here

希望这对某人有所帮助;)

这里 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

image

供查看: (最受推荐)

它适用于使用 UIView extension的所有类型的 UIView子类(视图、文本文件、标签等)

它更简单和方便。但唯一的条件是 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)

enter image description here
还有

// UITextField
self.txtArea.addLine(position: .bottom, color: UIColor.red, height: 1.0)

enter image description here

更新密码:

Swift 5.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

在 SwiftUI 中,有一个名为 DividerView与此完全匹配。您可以通过将它们嵌入到一个简单的 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)

Example Implementation