कोड Xcode, बीटा 7 के लिए अपडेट किया गया।
इसे प्राप्त करने के लिए आपको पैडिंग, स्क्रॉलव्यू या सूची की आवश्यकता नहीं है। हालांकि यह समाधान उनके साथ भी अच्छा खेलेगा। मैं यहां दो उदाहरणों सहित हूं।
यदि कोई उनमें से किसी के लिए कीबोर्ड प्रकट होता है, तो पहले वाला सभी टेक्स्ट को हटा देता है। लेकिन जरूरत पड़ने पर ही। यदि कीबोर्ड टेक्स्ट फ़ील्ड को नहीं छिपाता है, तो वे स्थानांतरित नहीं होंगे।
दूसरे उदाहरण में, दृश्य केवल सक्रिय पाठ्यक्षेत्र को छिपाने से बचने के लिए पर्याप्त चलता है।
दोनों उदाहरण अंत में पाए जाने वाले समान कॉमन कोड का उपयोग करते हैं: जियोमेट्रीगेटर और कीबोर्डगार्डियन
पहला उदाहरण (सभी पाठ्य-सामग्री दिखाएं)
struct ContentView: View {
@ObservedObject private var kGuardian = KeyboardGuardian(textFieldCount: 1)
@State private var name = Array<String>.init(repeating: "", count: 3)
var body: some View {
VStack {
Group {
Text("Some filler text").font(.largeTitle)
Text("Some filler text").font(.largeTitle)
}
TextField("enter text #1", text: $name[0])
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("enter text #2", text: $name[1])
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("enter text #3", text: $name[2])
.textFieldStyle(RoundedBorderTextFieldStyle())
.background(GeometryGetter(rect: $kGuardian.rects[0]))
}.offset(y: kGuardian.slide).animation(.easeInOut(duration: 1.0))
}
}
दूसरा उदाहरण (केवल सक्रिय क्षेत्र दिखाएं)
struct ContentView: View {
@ObservedObject private var kGuardian = KeyboardGuardian(textFieldCount: 3)
@State private var name = Array<String>.init(repeating: "", count: 3)
var body: some View {
VStack {
Group {
Text("Some filler text").font(.largeTitle)
Text("Some filler text").font(.largeTitle)
}
TextField("text #1", text: $name[0], onEditingChanged: { if $0 { self.kGuardian.showField = 0 } })
.textFieldStyle(RoundedBorderTextFieldStyle())
.background(GeometryGetter(rect: $kGuardian.rects[0]))
TextField("text #2", text: $name[1], onEditingChanged: { if $0 { self.kGuardian.showField = 1 } })
.textFieldStyle(RoundedBorderTextFieldStyle())
.background(GeometryGetter(rect: $kGuardian.rects[1]))
TextField("text #3", text: $name[2], onEditingChanged: { if $0 { self.kGuardian.showField = 2 } })
.textFieldStyle(RoundedBorderTextFieldStyle())
.background(GeometryGetter(rect: $kGuardian.rects[2]))
}.offset(y: kGuardian.slide).animation(.easeInOut(duration: 1.0))
}.onAppear { self.kGuardian.addObserver() }
.onDisappear { self.kGuardian.removeObserver() }
}
GeometryGetter
यह एक ऐसा दृश्य है जो अपने मूल दृश्य के आकार और स्थिति को अवशोषित करता है। इसे प्राप्त करने के लिए, इसे .background संशोधक के अंदर कहा जाता है। यह एक बहुत शक्तिशाली संशोधक है, न कि किसी दृश्य की पृष्ठभूमि को सजाने का एक तरीका। .Background (MyView ()) के दृश्य को पास करते समय, MyView को माता-पिता के रूप में संशोधित दृश्य मिल रहा है। ज्योमेट्रीरीडर का उपयोग करना माता-पिता की ज्यामिति को जानने के लिए दृश्य को संभव बनाता है।
उदाहरण के लिए: Text("hello").background(GeometryGetter(rect: $bounds))
पाठ दृश्य के आकार और स्थिति के साथ, और वैश्विक समन्वय स्थान का उपयोग करके, चर सीमाएं भरेंगे।
struct GeometryGetter: View {
@Binding var rect: CGRect
var body: some View {
GeometryReader { geometry in
Group { () -> AnyView in
DispatchQueue.main.async {
self.rect = geometry.frame(in: .global)
}
return AnyView(Color.clear)
}
}
}
}
अद्यतन मैंने DispatchQueue.main.async को जोड़ा, जबकि इसे प्रस्तुत किया जा रहा है, जबकि दृश्य की स्थिति को संशोधित करने की संभावना से बचने के लिए। ***
KeyboardGuardian
कीबोर्डगार्डियन का उद्देश्य, कीबोर्ड शो / छिपाने की घटनाओं पर नज़र रखना और गणना करना है कि दृश्य को स्थानांतरित करने के लिए कितना स्थान चाहिए।
अपडेट: मैंने स्लाइड को रीफ्रेश करने के लिए कीबोर्डगार्डियन को संशोधित किया, जब उपयोगकर्ता एक क्षेत्र से दूसरे में टैब करता है
import SwiftUI
import Combine
final class KeyboardGuardian: ObservableObject {
public var rects: Array<CGRect>
public var keyboardRect: CGRect = CGRect()
public var keyboardIsHidden = true
@Published var slide: CGFloat = 0
var showField: Int = 0 {
didSet {
updateSlide()
}
}
init(textFieldCount: Int) {
self.rects = Array<CGRect>(repeating: CGRect(), count: textFieldCount)
}
func addObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardDidHide(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)
}
func removeObserver() {
NotificationCenter.default.removeObserver(self)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc func keyBoardWillShow(notification: Notification) {
if keyboardIsHidden {
keyboardIsHidden = false
if let rect = notification.userInfo?["UIKeyboardFrameEndUserInfoKey"] as? CGRect {
keyboardRect = rect
updateSlide()
}
}
}
@objc func keyBoardDidHide(notification: Notification) {
keyboardIsHidden = true
updateSlide()
}
func updateSlide() {
if keyboardIsHidden {
slide = 0
} else {
let tfRect = self.rects[self.showField]
let diff = keyboardRect.minY - tfRect.maxY
if diff > 0 {
slide += diff
} else {
slide += min(diff, 0)
}
}
}
}