'OTC View autolayout in SwiftUI

I'm new to swiftui and swift basically, i made One-time-code screen, and here i have a problem. When i run project on my old phone (iphone 6) when keyboard appears, my textfield size changes (it gets very thin vertically). So i was wondering is there any way to add autolayout for older devices?

Here is my code

struct OneTimeCodeBoxes: View {
    
    @Binding var codeDict: [Int: String]
    @State var firstResponderIndex = 0
    var onCommit: (()->Void)?
    
    var body: some View {
        HStack {
            ForEach(0..<codeDict.count) { i in
                let isEmpty = codeDict[i]?.isEmpty == true
                
                OneTimeCodeInput(
                    index: i,
                    codeDict: $codeDict,
                    firstResponderIndex: $firstResponderIndex,
                    onCommit: onCommit
                )
                .aspectRatio(1, contentMode: .fit)
                .overlay(RoundedRectangle(cornerRadius: 10)
                    .stroke(lineWidth: isEmpty ? 1 : 2)
                    .foregroundColor(isEmpty ? .secondary : .green))
            }
        }
    }
}

struct OneTimeCodeBoxes_Previews: PreviewProvider {
    static var previews: some View {
        OneTimeCodeBoxes(codeDict: .constant([0: "", 1: "", 2: "", 3: ""]))
            .padding()
            .previewLayout(.sizeThatFits)
    }
}

Here is my OneTimeCodeInput part of code

struct OneTimeCodeInput: UIViewRepresentable {
    typealias UIViewType = UITextField
    
    let index: Int
    @Binding var codeDict: [Int: String]
    @Binding var firstResponderIndex: Int
    var onCommit: (()->Void)?
    
    
    class Coordinator: NSObject, UITextFieldDelegate {
        let index: Int
        @Binding var codeDict: [Int: String]
        @Binding var firstResponderIndex: Int
        
        private lazy var codeDigits: Int = codeDict.count
        
        init(index: Int, codeDict: Binding<[Int: String]>, firstResponderIndex: Binding<Int>) {
            self.index = index
            self._codeDict = codeDict
            self._firstResponderIndex = firstResponderIndex
        }
        
        @objc func textFieldEditingChanged(_ textField: UITextField) {
            print("textField.text!", textField.text!)
            
            guard textField.text!.count == codeDigits else { return }
            
            codeDict = textField.text!.enumerated().reduce(into: [Int: String](), { dict, tuple in
                let (index, char) = tuple
                dict.updateValue(String(char), forKey: index)
            })
            
            firstResponderIndex = codeDigits - 1
            
        }
        
        func textField(_ textField: UITextField,
                       shouldChangeCharactersIn range: NSRange,
                       replacementString string: String) -> Bool
        {
            print("replacementString", string)
            
            if string.isBackspace {
                codeDict.updateValue("", forKey: index)
                firstResponderIndex = max(0, textField.text == "" ? index - 1 : index)
                return false
            }

            for i in index..<min(codeDict.count, index + string.count) {
                codeDict.updateValue(string.stringAt(index: i - index), forKey: i)
                //                print(codeDict)
                firstResponderIndex = min(codeDict.count - 1, index + string.count)
            }
            
            
            return true
        }
        
    }
    
    func makeCoordinator() -> Coordinator {
        .init(index: index, codeDict: $codeDict, firstResponderIndex: $firstResponderIndex)
    }
    
    func makeUIView(context: Context) -> UITextField {
        let tf = BackspaceTextField(onDelete: {
            firstResponderIndex = max(0, index - 1)
        })
        tf.addTarget(context.coordinator, action: #selector(Coordinator.textFieldEditingChanged), for: .editingChanged)
        tf.delegate = context.coordinator
        tf.keyboardType = .numberPad
        tf.textContentType = .oneTimeCode
        tf.font = .preferredFont(forTextStyle: .largeTitle)
        tf.textAlignment = .center
        return tf
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = codeDict[index]
        
        if index == firstResponderIndex {
            uiView.becomeFirstResponder()
        }
        
        if index == firstResponderIndex,
           codeDict.values.filter({ !$0.isEmpty }).count == codeDict.count
        {
            onCommit?()
        }
    }
    
}


extension OneTimeCodeInput {
    
    
    class BackspaceTextField: UITextField {
        
        var onDelete: (()->Void)?
        
        init(onDelete: (()->Void)?) {
            self.onDelete = onDelete
            
            super.init(frame: .zero)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func deleteBackward() {
            super.deleteBackward()
            
            onDelete?()
        }
    }
    
}

This is how it shows on Ipnone13 simulator, and it's correct. I'm trying to do same on older devices enter image description here



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source