SwiftUI 布局与我们习惯的非常不同。目前我正在与TextFields战斗。特别是他们的可触摸区域。
TextField(
.constant(""),
placeholder: Text("My text field")
)
.padding([.leading, .trailing])
.font(.body)
Run Code Online (Sandbox Code Playgroud)
这导致一个非常小的TextField(高度明智的)
添加框架修改器修复了问题(视觉上)
TextField(
.constant(""),
placeholder: Text("My text field")
).frame(height: 60)
.padding([.leading, .trailing])
.font(.body)
Run Code Online (Sandbox Code Playgroud)
但可触摸区域保持不变。
我知道框架修饰符除了将 textField 包装在另一个具有指定高度的视图中之外什么都不做。
是否有任何相当于resizable()为Image,将允许更高的文本字段与更广泛的可触摸区域?
Dyl*_*and 30
该解决方案仅需要 a @FocusState、 anonTapGesture和 a.background带有颜色,并允许用户点击任何地方(包括填充区域)来聚焦该字段。使用 iOS 15 进行测试。
struct MyView: View {
@Binding var text: String
@FocusState private var isFocused: Bool
var body: some View {
TextField("", text: $text)
.padding()
.background(Color.gray)
.focused($isFocused)
.onTapGesture {
isFocused = true
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您发现自己在多个文本字段上执行此操作,则进行自定义TextFieldStyle将使事情变得更容易:
struct TappableTextFieldStyle: TextFieldStyle {
@FocusState private var textFieldFocused: Bool
func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding()
.background(Color.gray)
.focused($textFieldFocused)
.onTapGesture {
textFieldFocused = true
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后将其应用到您的文本字段:
TextField("", text: $text)
.textFieldStyle(TappableTextFieldStyle())
Run Code Online (Sandbox Code Playgroud)
如果您不介意使用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
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
TextField(...)
.padding(100)
.textFieldFocusableArea()
Run Code Online (Sandbox Code Playgroud)
由于我自己也使用这个,我会在github上保持更新:https : //gist.github.com/Amzd/d7d0c7de8eae8a771cb0ae3b99eab73d
Button 解决方案将添加可能不需要的样式和动画,因此我现在使用使用ResponderChain 包的新方法
import ResponderChain
extension View {
public func textFieldFocusableArea() -> some View {
self.modifier(TextFieldFocusableAreaModifier())
}
}
fileprivate struct TextFieldFocusableAreaModifier: ViewModifier {
@EnvironmentObject private var chain: ResponderChain
@State private var id = UUID()
func body(content: Content) -> some View {
content
.contentShape(Rectangle())
.responderTag(id)
.onTapGesture {
chain.firstResponder = id
}
}
}
Run Code Online (Sandbox Code Playgroud)
您必须在 SceneDelegate 中将 ResponderChain 设置为环境对象,请查看 ResponderChain 的 README 以获取更多信息。
小智 0
我不知道哪个更适合你。所以,我发布了两个解决方案。
1)如果只想缩小输入区域。
var body: some View {
Form {
HStack {
Spacer().frame(width: 30)
TextField("input text", text: $inputText)
Spacer().frame(width: 30)
}
}
}
Run Code Online (Sandbox Code Playgroud)
2)缩小整个表格区域
var body: some View {
HStack {
Spacer().frame(width: 30)
Form {
TextField("input text", text: $restrictInput.text)
}
Spacer().frame(width: 30)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2471 次 |
| 最近记录: |