【问题标题】:Change color of lines depending on the focus text field根据焦点文本字段更改线条颜色
【发布时间】:2021-10-31 21:49:34
【问题描述】:

我正在尝试创建一个在每个数字的底部都有虚线的 OTP 页面。我为每个数字使用了一个文本字段,总共使用了 6 个文本字段的 6 个数字。我希望下一行在用户输入整数之前改变颜色。

该行会改变它的颜色等等,这取决于哪一个是活动的文本字段。请注意,活动文本字段不应具有不同的颜色。只有下一个文本字段应该。所以如果我输入第一个数字,第二个应该已经是绿色了。

然后当我在第二个文本字段中输入一个数字时,第三个应该是绿色的。

看截图。

我仅使用 Xcode 12.3,无法使用 FocusState API 和 Xcode Beta 中使用的其他 API。

import SwiftUI

class ViewModel: ObservableObject {
    
    @Published var otpField = "" {
        didSet {
            guard otpField.count <= 6,
                  otpField.last?.isNumber ?? true else {
                otpField = oldValue
                
                return
            }
        }
    }
    var otp1: String {
        guard otpField.count >= 1 else {
            return ""
        }
        return String(Array(otpField)[0])
    }
    var otp2: String {
        guard otpField.count >= 2 else {
            return ""
        }
        return String(Array(otpField)[1])
    }
    var otp3: String {
        guard otpField.count >= 3 else {
            return ""
        }
        return String(Array(otpField)[2])
    }
    var otp4: String {
        guard otpField.count >= 4 else {
            return ""
        }
        return String(Array(otpField)[3])
    }
    
    var otp5: String {
        guard otpField.count >= 5 else {
            return ""
        }
        return String(Array(otpField)[4])
    }
    
    var otp6: String {
        guard otpField.count >= 6 else {
            return ""
        }
        return String(Array(otpField)[5])
    }
    
    @Published var borderColor: Color = .black
    @Published var isTextFieldDisabled = false
    var successCompletionHandler: (()->())?
}

struct ContentView: View {
    
      @StateObject var viewModel = ViewModel()
      @State var isFocused = false
      
      let textBoxWidth = UIScreen.main.bounds.width / 8
      let textBoxHeight = UIScreen.main.bounds.width / 8
      let spaceBetweenBoxes: CGFloat = 10
      let paddingOfBox: CGFloat = 1
      var textFieldOriginalWidth: CGFloat {
          (textBoxWidth*6)+(spaceBetweenBoxes*3)+((paddingOfBox*2)*3)
      }
      
      var body: some View {
              
              VStack {
                  
                  ZStack {
                      
                      HStack (spacing: spaceBetweenBoxes){
                        
                        otpText(text: viewModel.otp1)
                        otpText(text: viewModel.otp2)
                        otpText(text: viewModel.otp3)
                        otpText(text: viewModel.otp4)
                        otpText(text: viewModel.otp5)
                        otpText(text: viewModel.otp6)
                    
                      }
                      
                      TextField("", text: $viewModel.otpField)
                      .frame(width: isFocused ? 0 : textFieldOriginalWidth, height: textBoxHeight)
                      .disabled(viewModel.isTextFieldDisabled)
                      .textContentType(.oneTimeCode)
                      .foregroundColor(.clear)
                      .accentColor(.clear)
                      .background(Color.clear)
                      .keyboardType(.numberPad)
                  }
          }
      }
      
      private func otpText(text: String) -> some View {
          
          return Text(text)
              .font(.title)
              .frame(width: textBoxWidth, height: textBoxHeight)
              .background(VStack{
                Spacer()
                RoundedRectangle(cornerRadius: 1)
                    .frame(height: 1)
                    .overlay(Capsule().stroke(Color.green))
               })
              .padding(paddingOfBox)
      }
}

【问题讨论】:

    标签: swiftui colors textfield one-time-password


    【解决方案1】:

    我正在寻找答案...

    这里我更新了代码。

    查看:

    struct ContentView: View {
        
        @StateObject var viewModel = ViewModel()
        
        let textBoxWidth = UIScreen.main.bounds.width / 8
        let textBoxHeight = UIScreen.main.bounds.width / 8
        let spaceBetweenLines: CGFloat = 10
        let paddingOfBox: CGFloat = 1
        var textFieldOriginalWidth: CGFloat {
            (textBoxWidth*6)+(spaceBetweenLines*3)+((paddingOfBox*2)*3)
        }
        
        var body: some View {
            
            VStack {
                
                ZStack {
                    
                    HStack (spacing: spaceBetweenLines){
                        otpText(text: viewModel.otp1, isNextTyped: $viewModel.isNextTypedArr[0])
                        otpText(text: viewModel.otp2, isNextTyped: $viewModel.isNextTypedArr[1])
                        otpText(text: viewModel.otp3, isNextTyped: $viewModel.isNextTypedArr[2])
                        otpText(text: viewModel.otp4, isNextTyped: $viewModel.isNextTypedArr[3])
                        otpText(text: viewModel.otp5, isNextTyped: $viewModel.isNextTypedArr[4])
                        otpText(text: viewModel.otp6, isNextTyped: $viewModel.isNextTypedArr[5])
                    }
                    
                    
                    TextField("", text: $viewModel.otpField) { isEditing in
                        viewModel.isEditing = isEditing
                    }
                    .frame(width: viewModel.isEditing ? 0 : textFieldOriginalWidth, height: textBoxHeight)
                    .textContentType(.oneTimeCode)
                    .foregroundColor(.clear)
                    .accentColor(.clear)
                    .background(Color.clear)
                    .keyboardType(.numberPad)
                }
                
            }
        }
        
        private func otpText(text: String, isNextTyped: Binding<Bool>) -> some View {
            
            return Text(text)
                .font(.title)
                .frame(width: textBoxWidth, height: textBoxHeight)
                .background(VStack{
                    Spacer()
                    RoundedRectangle(cornerRadius: 1)
                        .frame(height: 0.5)
                        .foregroundColor(isNextTyped.wrappedValue ? .green : .black)
                })
                .padding(paddingOfBox)
        }
    }
    

    视图模型:

    class ViewModel: ObservableObject {
        
        @Published var otpField = "" {
            didSet {
                isNextTypedArr = Array(repeating: false, count: 6)
                guard otpField.count <= 6,
                      otpField.last?.isNumber ?? true else {
                    otpField = oldValue
                    return
                }
                if otpField.count < 6 {
                    isNextTypedArr[otpField.count] = true
                }
            }
        }
        var otp1: String {
            guard otpField.count >= 1 else {
                return ""
            }
            return String(Array(otpField)[0])
        }
        var otp2: String {
            guard otpField.count >= 2 else {
                return ""
            }
            return String(Array(otpField)[1])
        }
        var otp3: String {
            guard otpField.count >= 3 else {
                return ""
            }
            return String(Array(otpField)[2])
        }
        var otp4: String {
            guard otpField.count >= 4 else {
                return ""
            }
            return String(Array(otpField)[3])
        }
        
        var otp5: String {
            guard otpField.count >= 5 else {
                return ""
            }
            return String(Array(otpField)[4])
        }
        
        var otp6: String {
            guard otpField.count >= 6 else {
                return ""
            }
            return String(Array(otpField)[5])
        }
        
        @Published var isNextTypedArr = Array(repeating: false, count: 6)
        
        @Published var borderColor: Color = .black
        
        @Published var isEditing = false {
            didSet {
                isNextTypedArr = Array(repeating: false, count: 6)
                if isEditing && otpField.count < 6 {
                    isNextTypedArr[otpField.count] = true
                }
            }
        }
    }
    

    【讨论】:

    • 我只是在学习 SwiftUI。请问你是在哪里学的 SwiftUI?
    • 我从教程开始(仍在学习)。我推荐:Apple 教程、Sean Allen、LetsBuildThatApp、HackingWithSwift。这是一个好的开始,然后我会用不同的应用程序(宠物应用程序)挑战自己。
    • 谢谢@Alhomaidhi。你能解释一下这条线和它的用法吗? TextField("", text: $viewModel.otpField) { isEditing in viewModel.isEditing = isEditing }
    • 当然,这一行正在初始化一个TextField,其占位符为””,绑定字符串为$viewModel.otpField,而闭包接受Bool作为参数,类型为@ 987654327@ 在这种情况下,Bool 将是isEditing,系统将其作为标志发送。如果用户编辑 = true 如果用户不是 = false。
    • 感谢@Alhomaidhi,对于预览提供者,我注意到没有,当我尝试添加它时不会让我这样做。你知道这是为什么吗?
    猜你喜欢
    • 2017-04-20
    • 2021-01-09
    • 2018-06-25
    • 2012-02-03
    • 2022-07-21
    • 2013-07-22
    相关资源
    最近更新 更多