这是我的代码...
struct ContentView : View {
@State var showingTextField = false
@State var text = ""
var body: some View {
return VStack {
if showingTextField {
TextField($text)
}
Button(action: {
self.showingTextField.toggle()
}) {
Text ("Show")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想要的是当文本字段变为可见时,使文本字段成为第一响应者(即,获得焦点并弹出键盘)。
Jos*_*fer 81
使用SwiftUI-Introspect,您可以执行以下操作:
TextField("", text: $value)
.introspectTextField { textField in
textField.becomeFirstResponder()
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*ini 29
目前似乎还不太可能,但是您可以自己实现类似的功能。
您可以创建一个自定义文本字段并添加一个值,使其成为第一响应者。
struct CustomTextField: UIViewRepresentable {
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
var didBecomeFirstResponder = false
init(text: Binding<String>) {
_text = text
}
func textFieldDidChangeSelection(_ textField: UITextField) {
text = textField.text ?? ""
}
}
@Binding var text: String
var isFirstResponder: Bool = false
func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
return textField
}
func makeCoordinator() -> CustomTextField.Coordinator {
return Coordinator(text: $text)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
uiView.text = text
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
uiView.becomeFirstResponder()
context.coordinator.didBecomeFirstResponder = true
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:didBecomeFirstResponder需要确保文本字段仅成为第一响应者,而不是每次刷新时都由SwiftUI!
您将像这样使用它...
struct ContentView : View {
@State var text: String = ""
var body: some View {
CustomTextField(text: $text, isFirstResponder: true)
.frame(width: 300, height: 50)
.background(Color.red)
}
}
Run Code Online (Sandbox Code Playgroud)
附注:我添加了一个,frame因为它的行为不像股票TextField,这意味着幕后还有更多的事情要做。
更多关于Coordinators在这个优秀的WWDC 19讲:
整合SwiftUI
在Xcode 11.1上测试
Moj*_*ini 20
There is a new wrapper called @FocusState that controls the state of the keyboard and the focused keyboard ('aka' firstResponder).
If you use a focused modifier on the text fields, you can make them become focused:
or dismiss the keyboard by setting the variable to nil:
请注意,根据评论中的要求添加了文本绑定支持
struct LegacyTextField: UIViewRepresentable {
@Binding public var isFirstResponder: Bool
@Binding public var text: String
public var configuration = { (view: UITextField) in }
public init(text: Binding<String>, isFirstResponder: Binding<Bool>, configuration: @escaping (UITextField) -> () = { _ in }) {
self.configuration = configuration
self._text = text
self._isFirstResponder = isFirstResponder
}
public func makeUIView(context: Context) -> UITextField {
let view = UITextField()
view.addTarget(context.coordinator, action: #selector(Coordinator.textViewDidChange), for: .editingChanged)
view.delegate = context.coordinator
return view
}
public func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
configuration(uiView)
switch isFirstResponder {
case true: uiView.becomeFirstResponder()
case false: uiView.resignFirstResponder()
}
}
public func makeCoordinator() -> Coordinator {
Coordinator($text, isFirstResponder: $isFirstResponder)
}
public class Coordinator: NSObject, UITextFieldDelegate {
var text: Binding<String>
var isFirstResponder: Binding<Bool>
init(_ text: Binding<String>, isFirstResponder: Binding<Bool>) {
self.text = text
self.isFirstResponder = isFirstResponder
}
@objc public func textViewDidChange(_ textField: UITextField) {
self.text.wrappedValue = textField.text ?? ""
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
self.isFirstResponder.wrappedValue = true
}
public func textFieldDidEndEditing(_ textField: UITextField) {
self.isFirstResponder.wrappedValue = false
}
}
}
Run Code Online (Sandbox Code Playgroud)
struct ContentView: View {
@State var text = ""
@State var isFirstResponder = false
var body: some View {
LegacyTextField(text: $text, isFirstResponder: $isFirstResponder)
}
}
Run Code Online (Sandbox Code Playgroud)
LegacyTextField(text: $text, isFirstResponder: $isFirstResponder) {
$0.textColor = .red
$0.tintColor = .blue
}
Run Code Online (Sandbox Code Playgroud)
这种方法是完全适应的。例如,你可以看到如何在SwiftUI添加活动指示灯用同样的方法在这里
Cas*_*gen 12
我为跨平台第一响应者处理制作了这个小包,而无需在 iOS 13+ 上的SwiftUI中对视图进行子类化或制作自定义 ViewRepresentables
https://github.com/Amzd/ResponderChain
SceneDelegate.swift
...
// Set the ResponderChain as environmentObject
let rootView = ContentView().environmentObject(ResponderChain(forWindow: window))
...
Run Code Online (Sandbox Code Playgroud)
内容视图.swift
struct ContentView: View {
@EnvironmentObject var chain: ResponderChain
@State var showingTextField = false
@State var text = ""
var body: some View {
return VStack {
if showingTextField {
TextField($text).responderTag("field1").onAppear {
DispatchQueue.main.async {
chain.firstResponder = "field1"
}
}
}
Button(action: { self.showingTextField.toggle() }) {
Text ("Show")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
mah*_*han 11
macOS 12.0+,
Mac 催化剂 15.0+,
tvOS 15.0+,
watchOS 8.0+
focused(_:)如果您只有一个 TextField,请使用。专注(_:)
通过将其焦点状态绑定到给定的布尔状态值来修改此视图。
struct NameForm: View {
@FocusState private var isFocused: Bool
@State private var name = ""
var body: some View {
TextField("Name", text: $name)
.focused($isFocused)
Button("Submit") {
if name.isEmpty {
isFocued = true
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
focused(_:equals:)如果您有多个 TextField,请使用。专注(_:等于:)
通过将其焦点状态绑定到给定的状态值来修改此视图。
struct LoginForm: View {
enum Field: Hashable {
case usernameField
case passwordField
}
@State private var username = ""
@State private var password = ""
@FocusState private var focusedField: Field?
var body: some View {
Form {
TextField("Username", text: $username)
.focused($focusedField, equals: .usernameField)
SecureField("Password", text: $password)
.focused($focusedField, equals: .passwordField)
Button("Sign In") {
if username.isEmpty {
focusedField = .usernameField
} else if password.isEmpty {
focusedField = .passwordField
} else {
handleLogin(username, password)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Das*_*oga 10
就我而言,我想立即聚焦一个文本字段,我使用了.onappear函数
struct MyView: View {
@FocusState private var isTitleTextFieldFocused: Bool
@State private var title = ""
var body: some View {
VStack {
TextField("Title", text: $title)
.focused($isTitleTextFieldFocused)
}
.padding()
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.isTitleTextFieldFocused = true
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于那些最终在这里遇到但使用@Matteo Pacini的答案崩溃的人,请注意beta 4中的这一更改:无法分配给属性:'$ text'对于此块是不变的:
init(text: Binding<String>) {
$text = text
}
Run Code Online (Sandbox Code Playgroud)
应该使用:
init(text: Binding<String>) {
_text = text
}
Run Code Online (Sandbox Code Playgroud)
而且,如果您想让文本字段成为的第一响应者sheet,请注意,becomeFirstResponder只有在显示该文本字段后才能调用。换句话说,将@Matteo Pacini的文本字段直接放在sheet内容中会导致崩溃。
要解决此问题,请添加其他检查uiView.window != nil以检查文本字段的可见性。在焦点集中在视图层次结构中之后:
struct AutoFocusTextField: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: UIViewRepresentableContext<AutoFocusTextField>) -> UITextField {
let textField = UITextField()
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiView: UITextField, context:
UIViewRepresentableContext<AutoFocusTextField>) {
uiView.text = text
if uiView.window != nil, !uiView.isFirstResponder {
uiView.becomeFirstResponder()
}
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: AutoFocusTextField
init(_ autoFocusTextField: AutoFocusTextField) {
self.parent = autoFocusTextField
}
func textFieldDidChangeSelection(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的(例如@kipelovets 评论已接受的答案,例如@Eonil 的答案),我也没有找到任何适用于 macOS 的公认解决方案。但是,我有一些运气,使用NSViewControllerRepresentable使NSSearchField显示为 SwiftUI 视图中的第一响应者:
import Cocoa
import SwiftUI
class FirstResponderNSSearchFieldController: NSViewController {
@Binding var text: String
init(text: Binding<String>) {
self._text = text
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
let searchField = NSSearchField()
searchField.delegate = self
self.view = searchField
}
override func viewDidAppear() {
self.view.window?.makeFirstResponder(self.view)
}
}
extension FirstResponderNSSearchFieldController: NSSearchFieldDelegate {
func controlTextDidChange(_ obj: Notification) {
if let textField = obj.object as? NSTextField {
self.text = textField.stringValue
}
}
}
struct FirstResponderNSSearchFieldRepresentable: NSViewControllerRepresentable {
@Binding var text: String
func makeNSViewController(
context: NSViewControllerRepresentableContext<FirstResponderNSSearchFieldRepresentable>
) -> FirstResponderNSSearchFieldController {
return FirstResponderNSSearchFieldController(text: $text)
}
func updateNSViewController(
_ nsViewController: FirstResponderNSSearchFieldController,
context: NSViewControllerRepresentableContext<FirstResponderNSSearchFieldRepresentable>
) {
}
}
Run Code Online (Sandbox Code Playgroud)
示例 SwiftUI 视图:
struct ContentView: View {
@State private var text: String = ""
var body: some View {
FirstResponderNSSearchFieldRepresentable(text: $text)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
为了填补这个缺失的功能,你可以使用 Swift Package Manager 安装 SwiftUIX:
更多信息:https : //github.com/SwiftUIX/SwiftUIX
import SwiftUI
import SwiftUIX
struct ContentView : View {
@State var showingTextField = false
@State var text = ""
var body: some View {
return VStack {
if showingTextField {
CocoaTextField("Placeholder text", text: $text)
.isFirstResponder(true)
.frame(width: 300, height: 48, alignment: .center)
}
Button(action: { self.showingTextField.toggle() }) {
Text ("Show")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特用户界面
struct ContentView: View {
enum Field {
case firstTextfield
case secondTextfield
case lastTextfield
}
@State private var firstTextfield = ""
@State private var secondTextfield = ""
@State private var lastTextfield = ""
@FocusState private var focusedField: Field?
var body: some View {
VStack {
TextField("Enter anything on first textfield", text: $firstTextfield)
.focused($focusedField, equals: .firstTextfield)
.submitLabel(.next)
TextField("Enter anything on second textfield", text: $secondTextfield)
.focused($focusedField, equals: .secondTextfield)
.submitLabel(.next)
TextField("Enter anything on last textfield", text: $lastTextfield)
.focused($focusedField, equals: .lastTextfield)
.submitLabel(.join)
}
.onSubmit {
switch focusedField {
case .firstTextfield:
focusedField = .secondTextfield
case .secondTextfield:
focusedField = .lastTextfield
default:
focusedField = nil
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
描述:添加一个带有文本字段案例的枚举,以及一个包含在@FocusState该枚举类型中的属性。添加focused(_:equals:)修饰符以具有绑定值,等于枚举情况。现在,您可以将 更改focusedField为您希望光标所在的任何文本字段,或者通过将 nil 分配给focusedField 来退出第一响应者。
| 归档时间: |
|
| 查看次数: |
3078 次 |
| 最近记录: |