根据焦点文本字段更改线条颜色 [英] Change color of lines depending on the focus text field

查看:45
本文介绍了根据焦点文本字段更改线条颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create an OTP page that has dashed lines at the bottom of each digit. I used one text field for each digit and a total of 6 digits for 6 text fields are used. I want the next line to have it's color changed before the user enters an integer.

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

The line will change it's color and so forth, depending on which one is the active text field. Note that the active textfield should not have a different color. Only the next text field should. So if I key in the first digit, the 2nd one should already be green.

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

Then when I input a number in 2nd text field, the 3rd one should be green.

查看屏幕截图.

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

I am using Xcode 12.3 only and I cannot use FocusState APIs and other APIs that are used in Xcode Beta.

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)
      }
}

推荐答案

我正在寻找答案...

这里我更新了代码.

查看:

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
            }
        }
    }
}

这篇关于根据焦点文本字段更改线条颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆