如何在TextField(SwiftUI)上添加底线
我使用如何在TextField(SwiftUI)上添加底线,swift,textfield,swiftui,Swift,Textfield,Swiftui,我使用Rectangle()在TextField(SwiftUI)上添加底部边框 但是我想使用协议TextFieldStyle作为TextFieldStyle的底线,比如RoundedBorderTextFieldStyle 如何在不使用矩形的情况下为TextField创建自定义样式 要定义自定义样式,可以使用下面的代码。最终将使用矩形,但它位于自定义样式内部,而不是视图代码中。这是你想要的吗 注意:在Beta 3上测试 要使用自定义初始化器,请执行以下操作: struct ContentV
Rectangle()
在TextField(SwiftUI)上添加底部边框
但是我想使用协议TextFieldStyle
作为TextFieldStyle的底线,比如RoundedBorderTextFieldStyle
如何在不使用矩形的情况下为TextField创建自定义样式
要定义自定义样式,可以使用下面的代码。最终将使用矩形,但它位于自定义样式内部,而不是视图代码中。这是你想要的吗 注意:在Beta 3上测试 要使用自定义初始化器,请执行以下操作:
struct ContentView:View{
@国家私有变量username=“”
var body:一些观点{
VStack{
文本字段(“输入文本”,文本:$username)
.textFieldStyle(.myOwnStyle)
}.框架(宽度:300)
}
}
您的自定义初始化器实现:
public结构MyOwnTextFieldStyle:TextFieldStyle{
公共函数体(配置:TextField)->一些视图{
VStack(){
配置
.边框(颜色.蓝色,宽度:2)
.foregroundColor(颜色.黄色)
矩形()
.框架(高度:1.0,对齐方式:。底部)
.相对宽度(1)
.foregroundColor(颜色:红色)
}
}
}
扩展StaticMember,其中Base:TextFieldStyle{
公共静态变量myOwnStyle:MyOwnTextFieldStyle.Member{
StaticMember(MyOwnTextFieldStyle())
}
}
不过,kontiki的解决方案与Beta 6不兼容。
所以我创建了一个解决方案,在新视图中嵌入一个文本字段和一条绘制的底线。您只需复制代码并使用它,方法是编写TextFieldWithBottomLine(占位符:“我的占位符”)
用于如下视图:
我首先创建的是一条水平线:
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)
}
}
接下来,我创建一个视图,其中包含一个文本字段和下面的水平线:
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")
}
}
要查看它的实际操作,我创建了一个示例视图:
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()
}
}
符合TextFieldStyle协议
struct BottomLineTextFieldStyle: TextFieldStyle {
func _body(configuration: TextField<Self._Label>) -> some View {
VStack() {
configuration
Rectangle()
.frame(height: 0.5, alignment: .bottom)
.foregroundColor(Color.secondary)
}
}
}
换一种方式试试
struct ContentView: View {
@State var name: String = ""
var body: some View {
VStack {
// change frame as per requirement
TextField("Please enter text", text: $name)
.frame(width: 300, height: 30, alignment: .center)
.background(Color.gray.opacity(0.2))
LineView().frame(width: 300, height: 1.0, alignment: .center)
}
}
}
LineView:为ui视图创建自定义包装
struct LineView: UIViewRepresentable {
typealias UIViewType = UIView
func makeUIView(context: UIViewRepresentableContext<LineView>) -> UIView {
let view = UIView()
view.backgroundColor = UIColor.lightGray
return view
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LineView>) {
}
}
struct LineView:UIViewRepresentable{
typealias UIViewType=UIView
func makeUIView(上下文:UIViewRepresentableContext)->UIView{
let view=UIView()
view.backgroundColor=UIColor.lightGray
返回视图
}
func updateUIView(uiView:uiView,context:UIViewRepresentableContext){
}
}
我的解决方案是在文本字段下添加一个分隔符:
private let textFieldLength:CGFloat = 200
var body: some View {
VStack {
TextField("placeHolder", text: .constant("")).frame(width: textFieldLength, height: 30, alignment: .center)
Divider().frame(width: textFieldLength, height: 2, alignment: .center)
}
}
或者使用覆盖
TextField("", text: .constant(""))
.frame(width: textFieldLength, height: 30, alignment: .center)
.multilineTextAlignment(.leading)
.overlay(Divider().frame(width: textFieldLength, height: 2, alignment: .center), alignment: .bottom)
分隔符
可用于分隔其他内容的可视元素
您可以设置颜色
和高度
Divider()
.frame(height: 1)
.padding(.horizontal, 30)
.background(Color.red)
使用.overlay
TextField("mail@example.com", text: $email)
.overlay(VStack{Divider().offset(x: 0, y: 15)})
使用VStack
是为了确保分隔符始终是水平的。是的,这就是我要找的。谢谢。beta 6中不再有静态成员了。任何替换?请注意,通过使用.padding(.horizontal)
(不指定明确的长度)可以获得平台建议的间距。我认为overlay的解决方案比其他解决方案更干净。我喜欢第一个代码片段的简单性。好极了。如果不支持动画,我们可以将颜色
和高度
设置为私人let
。简直太棒了。最佳答案。
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()
}
}
}
TextField("mail@example.com", text: $email)
.overlay(VStack{Divider().offset(x: 0, y: 15)})