SwiftUI

swiftUI ios14 键盘自动上移的问题

SwiftUI更新到ios14以后,我们使用Textfiled时,会发现键盘弹出时,会导致view上移。不知道是不是ios14的bug?

解决方法有两种:

struct ContentView: View {
    @State var text: String = ""
    var body: some View {
        VStack {
            // 必须要加Spacer 要不不好用
            Spacer()
            TextField("asd", text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            Spacer()
        }
        .ignoresSafeArea(.keyboard, edges: .bottom)
    }
}
利用GeometryReader
GeometryReader { _ in
    ZStack {
        //PUT CONTENT HERE
    }.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
  • 目前尝试最有用的方法,在最根的MainView使用GeometryReader包住ZStack。
struct MainView: View {
  
    var body: some View {
        GeometryReader { _ in
            ZStack{
                 if A {
                   Aview()
                 } else if B {
                   Bview()
                 }
 
            }.edgesIgnoringSafeArea(.all)}
    }
    
}
  • 还有用.ignoresSafeArea(.keyboard, edges: .bottom)的写法

例1
struct ContentView: View {
    @State var text: String = ""

    var body: some View {
        if #available(iOS 14.0, *) {
            VStack {
                content
            }
            .ignoresSafeArea(.keyboard, edges: .bottom)
        } else {
            VStack {
                content
            }
        }
    }

    @ViewBuilder
    var content: some View {
        Spacer()
        TextField("asd", text: self.$text)
            .textFieldStyle(RoundedBorderTextFieldStyle())
        Spacer()
    }
}

例2
struct ContentView: View {
    @State var text: String = ""
    var body: some View {
        GeometryReader { _ in
            ...
        }
        .ignoresSafeArea(.keyboard, edges: .bottom)
    }
}

例3
struct ContentView: View {
    @State var text: String = ""
    var body: some View {
        VStack {
            Spacer()
            TextField("asd", text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            Spacer()
        }
        .ignoresSafeArea(.keyboard, edges: .bottom)
    }
}

键盘输入时,可能会遮挡入力框,我们可以活用inputAccessoryView

代码如下

struct NumberTextfield: UIViewRepresentable {
    
    @Binding var text: String
    @State var textbar: UITextField = UITextField(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
    
    func makeUIView(context: Context) -> UITextField {
        let view = UITextField()
        view.setLeftPaddingPoints(10)
        view.isUserInteractionEnabled = true
        view.backgroundColor = uiColorF9F9F9
        view.layer.borderColor = uiColorF9F9F9.cgColor
        view.layer.borderWidth = 1
        view.layer.cornerRadius = 4
        view.textColor = uiColor666666
        view.delegate = context.coordinator
        view.keyboardType = UIKeyboardType.numberPad
        view.clearButtonMode = .whileEditing
        view.frame = CGRect(x: 0, y: 0, width: 30, height: 40)
       
        textbar.font = UIFont.systemFont(ofSize: 23)
        textbar.backgroundColor = UIColor.init(red: 245 / 255, green: 245 / 255, blue: 245 / 255, alpha: 1)
        textbar.isEnabled = false
        view.inputAccessoryView = textbar
        
        return view
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
        textbar.text = uiView.text
    }
    
    func makeCoordinator() -> NumberTextfield.Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var control: NumberTextfield
        
        init(_ control: NumberTextfield) {
            self.control = control
        }
        
        func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
            self.control.text = textField.text!
            return true
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            if((textField.text?.count)! > 10) {
                textField.text! = String(textField.text!.prefix(10))
            }
            self.control.text = textField.text!
        }
    
    }
    
}
struct TextAreaView: UIViewRepresentable {
    
    @Binding var text: String
    @State var textbar: UITextView = UITextView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100))
    
    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.font = UIFont.systemFont(ofSize: 15)
        view.isUserInteractionEnabled = true
        view.layer.cornerRadius = 4
        view.backgroundColor = uiColorF9F9F9
        view.delegate = context.coordinator
        view.keyboardType = .default
        
        textbar.isScrollEnabled = true
        textbar.isEditable = false
        textbar.isUserInteractionEnabled = false
        textbar.textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 8, right: 4)
        textbar.font = UIFont.systemFont(ofSize: 19)
        textbar.backgroundColor = UIColor.init(red: 245 / 255, green: 245 / 255, blue: 245 / 255, alpha: 1)
        view.inputAccessoryView = textbar
        
        return view
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        textbar.text = uiView.text
    }
    
    func makeCoordinator() -> TextAreaView.Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
        var control: TextAreaView
        
        init(_ control: TextAreaView) {
            self.control = control
        }
      
        func textViewDidChange(_ textView: UITextView) {
            self.control.text = textView.text!
            self.control.textbar.text = textView.text!
            //let range = NSMakeRange(textView.text.count - 1, 0)
            self.control.textbar.scrollRangeToVisible(textView.selectedRange)
        }
    }
}