【问题标题】:Change style of TextField on focus (without a variable per field)更改焦点上 TextField 的样式(每个字段没有变量)
【发布时间】:2021-05-11 15:34:31
【问题描述】:

我有一个带有嵌套迷你表单的表单(用于添加项目),因此您可以添加更多项目(从而向表单动态添加更多字段)。我想更改用户当前正在输入的字段的样式(焦点状态)。

我见过一些solutions using state vars to keep track of each field,但由于我的字段是动态添加的,因此跟踪未知数量的变量听起来比应该的要麻烦。

TextField("", text: $viewModel.item.name, onEditingChanged: {
     if $0 {
        //Put something here to change the border or background color directly, maybe reference to the field id or tag?
     }
 })
.modifier(TextInputStyle(isDisabled : false, isEditing: something)) // Or somehow pass a value here without having to make a state variable

更新:感谢一些帮助,我离得更近了,但现在我在通过按钮(切换isDisabled)以编程方式禁用该字段时遇到了一些错误。

在控制台中,我得到了这个:

=== AttributeGraph:通过属性 1864952 检测到循环 === === AttributeGraph:通过属性 1864952 检测到循环 === === AttributeGraph:通过属性 1864952 检测到循环 === === AttributeGraph:通过属性 1866776 检测到循环 === === AttributeGraph:通过属性 1865304 检测到循环 === === AttributeGraph:通过属性 1865304 检测到循环 === === AttributeGraph:通过属性 1862584 检测到循环 === === AttributeGraph:通过属性 1847528 检测到循环 === === AttributeGraph:通过属性 1847528 检测到循环 === === AttributeGraph:通过属性 1865304 检测到循环 === === AttributeGraph:通过属性 1878320 检测到循环 === === AttributeGraph:通过属性 1878200 检测到循环 === === AttributeGraph:通过属性 1878320 检测到循环 === === AttributeGraph:通过属性 1878200 检测到循环 === 2021-02-08 12:52:20.918323-0600 App [23659:862912] [SwiftUI] 在视图更新期间修改状态,这将导致未定义的行为。

【问题讨论】:

  • 你能把它和文字比较一下吗?如果 $viewModel.item.name.count > 1...

标签: swiftui


【解决方案1】:

您可以将TextField 抽象为使用@State 变量的自己的组件,但您只会使用它一次,然后重用该组件。

小例子:

struct ContentView: View {
    
    @State var disabled = false
    
    @State var text = "test" //these would come from your view model -- created multiple state for the text just for testing, but doesn't affect the highlighting behavior
    @State var text2 = "test2"
    @State var text3 = "test3"
    
    var body: some View {
        
        VStack {
            HighlightableTextField(text: $text, disabled: disabled)
            HighlightableTextField(text: $text2, disabled: disabled)
            HighlightableTextField(text: $text3, disabled: disabled)
            
            Button(disabled ? "Enable" : "Disable") {
                disabled.toggle()
            }
        }
        
    }
}

struct HighlightableTextField : View {
    @Binding var text : String
    var disabled : Bool
    @State private var isEditting = false
    
    var body: some View {
        TextField("", text: $text, onEditingChanged: { editing in
            DispatchQueue.main.async {
                isEditting = editing
            }
        })
        .disabled(disabled)
        .background(isEditting ? Color.red : Color.clear)
    }
}

我正在使用 @State 变量进行文本绑定,但这仍然可以链接到您的视图模型,就像您的原始代码一样。另外,我选择只传入 String 绑定,但显然您也可以传入任何其他需要的参数。

【讨论】:

  • 经过一些测试,我在isEditing = $0 行收到警告:“在视图更新期间修改状态,这将导致未定义的行为。”以及控制台中的一堆消息,如下所示:=== AttributeGraph:通过属性 1850392 检测到循环 ===。我会更新我的问题
  • 好的 -- 我会寻找更新 这在我的测试期间不会发生。这是使用我的代码还是您为使用而修改的版本?
  • 谢谢。当我添加一个按钮来切换字段以便启用或禁用它时,问题就出现了。
  • 经过实验添加禁用属性并更新了我的代码后,我能够在最后重现它。使用DispatchQueue.main.async在下一个运行循环中调用isEditing
  • 感谢您的帮助。我仍然收到控制台警告:=== AttributeGraph:通过属性 1877176 === 检测到循环,但这与切换 .disabled(isDisabled) 有关。当我注释掉该行时,没有错误或警告。哦,好吧...
【解决方案2】:

我已经创建了自定义文本字段视图,所以,它可以重复使用....

struct TextFieldView: View {
    
    @State var textField1 = "A"
    @State var textField2 = "B"
    @State var textField3 = "C"
    
    var body: some View {
        VStack {
            CustomTextField(value: $textField1)
            CustomTextField(value: $textField2)
            CustomTextField(value: $textField3)
        }
        .padding()
    }
}

// TestField struct separation
struct CustomTextField : View {
    // Bind textfield string input value 
    @Binding var value : String
    // Manage focus point indication
    @State private var isFocused = false
    
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 10, style: .continuous)
                .stroke(isFocused ? Color.blue : Color.gray.opacity(0.4), lineWidth: 2)
            TextField("", text: $value, onEditingChanged: {
                isFocused = $0
            }).padding()
        }
        .frame(height: 50)
        .padding()
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 2021-05-13
    • 2019-05-13
    • 2020-02-10
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多