Nil*_*ils 25 xcode modal-dialog textfield swift swiftui
我正在使用模态将名称添加到列表中。当显示模态时,我想自动聚焦 TextField,如下所示:
我还没有找到任何合适的解决方案。
为了做到这一点,是否已经在 SwiftUI 中实现了任何东西?
谢谢你的帮助。
var modal: some View {
NavigationView{
VStack{
HStack{
Spacer()
TextField("Name", text: $inputText) // autofocus this!
.textFieldStyle(DefaultTextFieldStyle())
.padding()
.font(.system(size: 25))
// something like .focus() ??
Spacer()
}
Button(action: {
if self.inputText != ""{
self.players.append(Player(name: self.inputText))
self.inputText = ""
self.isModal = false
}
}, label: {
HStack{
Text("Add \(inputText)")
Image(systemName: "plus")
}
.font(.system(size: 20))
})
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(10)
Spacer()
}
.navigationBarTitle("New Player")
.navigationBarItems(trailing: Button(action: {self.isModal=false}, label: {Text("Cancel").font(.system(size: 20))}))
.padding()
}
}
Run Code Online (Sandbox Code Playgroud)
Moj*_*ini 35
有一个名为的新包装器@FocusState
,用于控制键盘和聚焦键盘(又名firstResponder)的状态。
\n\n\xe2\x9a\xa0\xef\xb8\x8f 请注意,如果你想让它在初始时间聚焦,你必须应用延迟。这是 SwiftUI 的一个已知错误。
\n
如果您focused
在文本字段上使用修饰符,则可以使它们成为焦点,例如,您可以focusedField
在代码中设置该属性以使绑定的文本字段变为活动状态:
或通过将变量设置为关闭键盘nil
:
不要忘记观看WWDC2021 的 SwiftUI 会议中的 Direct 和 Reflect Focus
\n旧但工作:
\n请注意,根据评论中的要求添加了文本绑定支持
\nstruct LegacyTextField: UIViewRepresentable {\n @Binding public var isFirstResponder: Bool\n @Binding public var text: String\n\n public var configuration = { (view: UITextField) in }\n\n public init(text: Binding<String>, isFirstResponder: Binding<Bool>, configuration: @escaping (UITextField) -> () = { _ in }) {\n self.configuration = configuration\n self._text = text\n self._isFirstResponder = isFirstResponder\n }\n\n public func makeUIView(context: Context) -> UITextField {\n let view = UITextField()\n view.addTarget(context.coordinator, action: #selector(Coordinator.textViewDidChange), for: .editingChanged)\n view.delegate = context.coordinator\n return view\n }\n\n public func updateUIView(_ uiView: UITextField, context: Context) {\n uiView.text = text\n switch isFirstResponder {\n case true: uiView.becomeFirstResponder()\n case false: uiView.resignFirstResponder()\n }\n }\n\n public func makeCoordinator() -> Coordinator {\n Coordinator($text, isFirstResponder: $isFirstResponder)\n }\n\n public class Coordinator: NSObject, UITextFieldDelegate {\n var text: Binding<String>\n var isFirstResponder: Binding<Bool>\n\n init(_ text: Binding<String>, isFirstResponder: Binding<Bool>) {\n self.text = text\n self.isFirstResponder = isFirstResponder\n }\n\n @objc public func textViewDidChange(_ textField: UITextField) {\n self.text.wrappedValue = textField.text ?? ""\n }\n\n public func textFieldDidBeginEditing(_ textField: UITextField) {\n self.isFirstResponder.wrappedValue = true\n }\n\n public func textFieldDidEndEditing(_ textField: UITextField) {\n self.isFirstResponder.wrappedValue = false\n }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\nstruct ContentView: View {\n @State var text = ""\n @State var isFirstResponder = false\n\n var body: some View {\n LegacyTextField(text: $text, isFirstResponder: $isFirstResponder)\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\nLegacyTextField(text: $text, isFirstResponder: $isFirstResponder) {\n $0.textColor = .red\n $0.tintColor = .blue\n}\n
Run Code Online (Sandbox Code Playgroud)\n
Ans*_*ngh 20
由于 Responder Chain 不是通过 SwiftUI 呈现来消费的,所以我们必须使用 UIViewRepresentable 来消费它。我已经制定了一个解决方法,它的工作方式类似于我们使用 UIKit 的方式。
struct CustomTextField: UIViewRepresentable {
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
@Binding var nextResponder : Bool?
@Binding var isResponder : Bool?
init(text: Binding<String>,nextResponder : Binding<Bool?> , isResponder : Binding<Bool?>) {
_text = text
_isResponder = isResponder
_nextResponder = nextResponder
}
func textFieldDidChangeSelection(_ textField: UITextField) {
text = textField.text ?? ""
}
func textFieldDidBeginEditing(_ textField: UITextField) {
DispatchQueue.main.async {
self.isResponder = true
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
DispatchQueue.main.async {
self.isResponder = false
if self.nextResponder != nil {
self.nextResponder = true
}
}
}
}
@Binding var text: String
@Binding var nextResponder : Bool?
@Binding var isResponder : Bool?
var isSecured : Bool = false
var keyboard : UIKeyboardType
func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.isSecureTextEntry = isSecured
textField.autocapitalizationType = .none
textField.autocorrectionType = .no
textField.keyboardType = keyboard
textField.delegate = context.coordinator
return textField
}
func makeCoordinator() -> CustomTextField.Coordinator {
return Coordinator(text: $text, nextResponder: $nextResponder, isResponder: $isResponder)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
uiView.text = text
if isResponder ?? false {
uiView.becomeFirstResponder()
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用这个组件......
struct ContentView : View {
@State private var username = ""
@State private var password = ""
// set true , if you want to focus it initially, and set false if you want to focus it by tapping on it.
@State private var isUsernameFirstResponder : Bool? = true
@State private var isPasswordFirstResponder : Bool? = false
var body : some View {
VStack(alignment: .center) {
CustomTextField(text: $username,
nextResponder: $isPasswordFirstResponder,
isResponder: $isUsernameFirstResponder,
isSecured: false,
keyboard: .default)
// assigning the next responder to nil , as this will be last textfield on the view.
CustomTextField(text: $password,
nextResponder: .constant(nil),
isResponder: $isPasswordFirstResponder,
isSecured: true,
keyboard: .default)
}
.padding(.horizontal, 50)
}
}
Run Code Online (Sandbox Code Playgroud)
这里 isResponder 是将响应者分配给当前文本字段,而 nextResponder 是做出第一个响应,因为当前文本字段会放弃它。
这非常容易,SwiftUIX
我很惊讶更多人不知道这一点。
import SwiftUIX
.CocoaTextField
代替TextField
来使用功能.isFirstResponder(true)
。CocoaTextField("Confirmation Code", text: $confirmationCode)
.isFirstResponder(true)
Run Code Online (Sandbox Code Playgroud)
我试图根据以前的答案使其变得简单,这使得视图出现时键盘出现,没有其他。刚刚在iOS 16上测试,确实自动出现,无需设置延迟。
struct MyView: View {
@State private var answer = ""
@FocusState private var focused: Bool // 1. create a @FocusState here
var body: some View {
VStack {
TextField("", text: $answer)
.focused($focused) // 2. set the binding here
}
.onAppear {
focused = true // 3. pop the keyboard on appear
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13723 次 |
最近记录: |