SwiftUI TextField可触摸区域

时间:2019-06-27 17:01:10

标签: swiftui

SwiftUI的布局与我们习惯的有很大不同。目前,我正在与TextField对抗。特别是他们的可触摸区域。

TextField(
    .constant(""),
    placeholder: Text("My text field")
    )
        .padding([.leading, .trailing])
        .font(.body)

这导致TextField非常小(高度)

enter image description here

添加frame修饰符(视觉上)解决了该问题

TextField(
    .constant(""),
    placeholder: Text("My text field")
    ).frame(height: 60)
        .padding([.leading, .trailing])
        .font(.body)

但可触摸区域保持不变。

我知道一个事实,除了框架文本修饰符可以将textField包装到具有指定高度的另一个View中之外,什么都不做。

是否有与resizable()等效的Image可以允许更高的TextField以及更宽的可触摸区域?

5 个答案:

答案 0 :(得分:2)

如果您不介意使用Introspect,可以通过保存UITextField并在按下按钮时调用$来实现。

becomeFirstResponder()

用法示例:

extension View {
    public func textFieldFocusableArea() -> some View {
        TextFieldButton { self.contentShape(Rectangle()) }
    }
}

fileprivate struct TextFieldButton<Label: View>: View {
    init(label: @escaping () -> Label) {
        self.label = label
    }

    var label: () -> Label

    private var textField = Weak<UITextField>(nil)

    var body: some View {
        Button(action: {
            self.textField.value?.becomeFirstResponder()
        }, label: {
            label().introspectTextField {
                self.textField.value = $0
            }
        }).buttonStyle(PlainButtonStyle())
    }
}

/// Holds a weak reference to a value
public class Weak<T: AnyObject> {
    public weak var value: T?
    public init(_ value: T?) {
        self.value = value
    }
}

由于我也是自己使用它,因此我将在github上对其进行更新:https://gist.github.com/Amzd/d7d0c7de8eae8a771cb0ae3b99eab73d

答案 1 :(得分:1)

快速的解决方法是将TextField放在一个按钮中,无论您在何处点击(在按钮中),它都会使键盘打开;我知道这不是解决方案,但可以完成工作。

答案 2 :(得分:0)

您可以使用.font(.largeTitle)或任何customFont,

代码:

VStack {
         //using a large title
        TextField(.constant("Name"),placeholder: Text("My text field"))
            .textFieldStyle(.roundedBorder)
            .font(.largeTitle)
            .padding()

         //using custom font
        TextField(.constant("someText"),placeholder: Text("My Textfield"))
            .font(.custom("Arial", size: 70))
            //.font(.largeTitle)
            .textFieldStyle(.roundedBorder)
            .padding()
    }

但是,当我必须删除文本字段时,我注意到TextField的旧大小相同。 不知道这不是错误。

答案 3 :(得分:0)

我不知道哪个更适合您。 因此,我发布了两种解决方案。

1)如果只想缩小输入区域。

enter image description here

  var body: some View {
     Form {
        HStack {
           Spacer().frame(width: 30)
           TextField("input text", text: $inputText)
           Spacer().frame(width: 30)
        }
     }
   }

2)缩小整个表单区域

enter image description here

  var body: some View {
    HStack {
        Spacer().frame(width: 30)
        Form {
            TextField("input text", text: $restrictInput.text)
        }
        Spacer().frame(width: 30)
    }
 }

答案 4 :(得分:0)

稍微变通但有效。

  struct CustomTextField: View {
@State var name = ""
@State var isFocused = false
let textFieldsize : CGFloat = 20
var textFieldTouchAbleHeight : CGFloat = 200
var body: some View {
        ZStack {
            HStack{
                Text(name)
                    .font(.system(size: textFieldsize))
                    .lineLimit(1)
                    .foregroundColor(isFocused ? Color.clear : Color.black)
                    .disabled(true)
                Spacer()
            }
            .frame(alignment: .leading)
            TextField(name, text: $name , onEditingChanged: { editingChanged in
                isFocused = editingChanged
            })
            .font(.system(size: isFocused ? textFieldsize :  textFieldTouchAbleHeight ))
            .foregroundColor(isFocused ? Color.black  : Color.clear)
            .frame( height: isFocused ? 50 :  textFieldTouchAbleHeight , alignment: .leading)
             
        }.frame(width: 300, height: textFieldTouchAbleHeight + 10,alignment: .leading)
        .disableAutocorrection(true)
        .background(Color.white)
        .padding(.horizontal,10)
        .padding(.vertical,10)
        .border(Color.red, width: 2) 
    
      }

    }