Add Bottom Border Line to UI Textfield View in Swiftui/Swift/Objective-C/Xamarin

Add bottom border line to UI TextField view in SwiftUI / Swift / Objective-C / Xamarin

I am creating custom textField to make it reusable component for 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)
}
}
}

Usage:

@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

I am using Visual Formatting Language (VFL) here, This will allow adding a line to any UIControl.

You can create a UIView extension class like UIView+Extention.swift

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

Usage:

textField.addLine(position: .LINE_POSITION_BOTTOM, color: .darkGray, width: 0.5)

Objective C:

You can add this helper method to your global helper class(I used global class method) or in the same view controller(using an instance method).

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;
}
}

Usage:

[self addLine:self.textField atPosition:LINE_POSITION_TOP withColor:[UIColor darkGrayColor] lineWitdh:0.5];

Xamarin code:

 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;

UITextField having bottom border only in Objective-C

First:

Add and import QuartzCore framework.

#import 

Second:

CALayer *border = [CALayer layer];
CGFloat borderWidth = 2;
border.borderColor = [UIColor grayColor].CGColor;
border.frame = CGRectMake(0, textField.frame.size.height - borderWidth, textField.frame.size.width, textField.frame.size.height);
border.borderWidth = borderWidth;
[textField.layer addSublayer:border];
textField.layer.masksToBounds = YES;

EDIT:

If you have more TextFields, make one common method which takes UITextField and applies border to it like below:

-(void)SetTextFieldBorder :(UITextField *)textField{

CALayer *border = [CALayer layer];
CGFloat borderWidth = 2;
border.borderColor = [UIColor grayColor].CGColor;
border.frame = CGRectMake(0, textField.frame.size.height - borderWidth, textField.frame.size.width, textField.frame.size.height);
border.borderWidth = borderWidth;
[textField.layer addSublayer:border];
textField.layer.masksToBounds = YES;

}

Pass your TextField as follows to set Bottom Border:

[self SetTextFieldBorder:YourTextField];

Creating a textfield with only bottom Line in Ios

Yes it is possible. Here is how to do it:

CALayer *border = [CALayer layer];
CGFloat borderWidth = 2;
border.borderColor = [UIColor darkGrayColor].CGColor;
border.frame = CGRectMake(0, textField.frame.size.height - borderWidth, textField.frame.size.width, textField.frame.size.height);
border.borderWidth = borderWidth;
[textField.layer addSublayer:border];
textField.layer.masksToBounds = YES;

Hope this helps!!

How can I add a bottom line on TextField (SwiftUI)

The solution of kontiki does not work with Beta 6, though.
So I created a solution where I embed a TextField and a drawn bottom line in a new view. You can just copy the code and use it by writing TextFieldWithBottomLine(placeholder: "My placeholder") Used in a view it looks like:

Usage of TextView with bottom line

The first thing I create is a horizontal line:

import SwiftUI

struct HorizontalLineShape: Shape {

func path(in rect: CGRect) -> Path {

let fill = CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height)
var path = Path()
path.addRoundedRect(in: fill, cornerSize: CGSize(width: 2, height: 2))

return path
}
}

struct HorizontalLine: View {
private var color: Color? = nil
private var height: CGFloat = 1.0

init(color: Color, height: CGFloat = 1.0) {
self.color = color
self.height = height
}

var body: some View {
HorizontalLineShape().fill(self.color!).frame(minWidth: 0, maxWidth: .infinity, minHeight: height, maxHeight: height)
}
}

struct HorizontalLine_Previews: PreviewProvider {
static var previews: some View {
HorizontalLine(color: .black)
}
}

Next I create a view that contains a TextField and the HorizontalLine below:

import SwiftUI

struct TextFieldWithBottomLine: View {
@State var text: String = ""
private var placeholder = ""
private let lineThickness = CGFloat(2.0)

init(placeholder: String) {
self.placeholder = placeholder
}

var body: some View {
VStack {
TextField(placeholder, text: $text)
HorizontalLine(color: .black)
}.padding(.bottom, lineThickness)
}
}

struct TextFieldWithBottomLine_Previews: PreviewProvider {
static var previews: some View {
TextFieldWithBottomLine(placeholder: "My placeholder")
}
}

To see it in action I created a sample view:

import SwiftUI

struct SampleView: View {
@State var text: String = ""
@ObservedObject var model: LoginModel

init() {
self.model = LoginModel()
}

init(model: LoginModel) {
self.model = model
}

var body: some View {
TextFieldWithBottomLine(placeholder: "My placeholder").padding(24)
}

func initialActions() {

}

func reactOnButtonClick() {

}
}

struct SampleView_Previews: PreviewProvider {
static var previews: some View {
SampleView()
}
}

How to only show bottom border of UITextField in Swift

Try to do by this way, with Swift 5.1:

var bottomLine = CALayer()
bottomLine.frame = CGRect(x: 0.0, y: myTextField.frame.height - 1, width: myTextField.frame.width, height: 1.0)
bottomLine.backgroundColor = UIColor.white.cgColor
myTextField.borderStyle = UITextField.BorderStyle.none
myTextField.layer.addSublayer(bottomLine)

You have to set the borderStyle property to None

If you are using the autolayout then set perfect constraint else bottomline will not appear.

Hope it helps.

how to add % symbol at the end textField in swiftUI

for this i made a function and on right side put a image as percentage that fixed my issue

    func makeUIView(context: Context) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
textField.tintColor = UIColor.clear
textField.rightView = makeImageForTextField()
textField.rightViewMode = .always
textField.keyboardType = .decimalPad
let toolBar = UIToolbar(
frame: CGRect(
x: 0, y: 0,
width: textField.frame.size.width,
height: 44
)
)
let doneButton = UIBarButtonItem(
title: "Done",
style: .done,
target: self,
action: #selector(textField.doneButtonTapped(button:))
)

toolBar.items = [doneButton]
toolBar.setItems([doneButton], animated: true)
textField.inputAccessoryView = toolBar
return textField
}

private func makeImageForTextField() -> UIButton {
let button = UIButton()
button.setImage(UIImage(systemName: "percent"), for: .normal)
button.tintColor = .black
button.isUserInteractionEnabled = false
return button
}

TextField stroke border text with SwiftUI

Here is a solution using .trim on two RoundedRectangles based on the length of the label text, which should give you the result you want:

struct CustomTextField: View {
let placeholder: String
@Binding var text: String

@State private var width = CGFloat.zero
@State private var labelWidth = CGFloat.zero

var body: some View {
TextField(placeholder, text: $text)
.foregroundColor(.gray)
.font(.system(size: 20))
.padding(EdgeInsets(top: 15, leading: 10, bottom: 15, trailing: 10))
.background {
ZStack {
RoundedRectangle(cornerRadius: 5)
.trim(from: 0, to: 0.55)
.stroke(.gray, lineWidth: 1)
RoundedRectangle(cornerRadius: 5)
.trim(from: 0.565 + (0.44 * (labelWidth / width)), to: 1)
.stroke(.gray, lineWidth: 1)
Text(placeholder)
.foregroundColor(.gray)
.overlay( GeometryReader { geo in Color.clear.onAppear { labelWidth = geo.size.width }})
.padding(2)
.font(.caption)
.frame(maxWidth: .infinity,
maxHeight: .infinity,
alignment: .topLeading)
.offset(x: 20, y: -10)

}
}
.overlay( GeometryReader { geo in Color.clear.onAppear { width = geo.size.width }})
.onChange(of: width) { _ in
print("Width: ", width)
}
.onChange(of: labelWidth) { _ in
print("labelWidth: ", labelWidth)
}


}
}

Sample Image



Related Topics



Leave a reply



Submit