How can I add a bottom line on TextField (SwiftUI)
Divider
A visual element that can be used to separate other content.
You can set color
and height
Divider()
.frame(height: 1)
.padding(.horizontal, 30)
.background(Color.red)
struct LoginField: View {
@State private var email: String = ""
@State private var password: String = ""
var body: some View {
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
TextField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
Spacer()
}
}
}
To define a custom style, you can use the code below. The Rectangle is used eventually, but inside the custom style, not in your view code. Is this what you want?
Note: Tested on Beta 3
To use your custom initialiser:
struct ContentView : View {
@State private var username = ""
var body: some View {
VStack {
TextField("Enter text", text: $username)
.textFieldStyle(.myOwnStyle)
}.frame(width:300)
}
}
Your custom initialiser implementation:
public struct MyOwnTextFieldStyle: TextFieldStyle {
public func _body(configuration: TextField<Self.Label>) -> some View {
VStack() {
configuration
.border(Color.blue, width: 2)
.foregroundColor(Color.yellow)
Rectangle()
.frame(height: 1.0, alignment: .bottom)
.relativeWidth(1)
.foregroundColor(Color.red)
}
}
}
extension StaticMember where Base : TextFieldStyle {
public static var myOwnStyle: MyOwnTextFieldStyle.Member {
StaticMember<MyOwnTextFieldStyle>(MyOwnTextFieldStyle())
}
}
Using .overlay
TextField("[email protected]", text: $email)
.overlay(VStack{Divider().offset(x: 0, y: 15)})
the use of VStack
is to ensure that the Divider
is always horizontal.
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:
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()
}
}