Ich versuche, einen Eingabebildschirm für das iPhone zu erstellen. Der Bildschirm verfügt über eine Reihe von Eingabefeldern. Die meisten davon befinden sich oben auf dem Bildschirm, zwei Felder jedoch unten. Wenn der Benutzer versucht, den Text am unteren Rand des Bildschirms zu bearbeiten, wird die Tastatur eingeblendet und der Bildschirm wird abgedeckt. Ich habe eine einfache Lösung gefunden, um den Bildschirm nach oben zu bewegen, wenn dies passiert, aber das Ergebnis ist, dass der Bildschirm always immer nach oben bewegt wird und die Felder oben auf dem Bildschirm außerhalb der Reichweite bleiben, wenn der Benutzer versucht, diese zu bearbeiten .
Gibt es eine Möglichkeit, den Bildschirm only verschieben zu lassen, wenn die unteren Felder bearbeitet werden?
Ich habe diesen Code verwendet, den ich gefunden habe hier :
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(sender: NSNotification) {
self.view.frame.Origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.Origin.y += 150
}
Ihr Problem ist in diesem Dokument von Apple gut beschrieben. Beispielcode auf dieser Seite (unter Listing 4-1
) erfüllt genau das, was Sie benötigen. Nur dann wird die Ansicht gescrollt, wenn die aktuelle Bearbeitung unter der Tastatur erfolgen soll. Sie brauchen nur Ihre benötigten Steuerelemente in eine scrollViiew zu legen. Das einzige Problem ist, dass dies Objective-C ist und ich denke, Sie brauchen es in Swift..so..hier ist es:
Deklarieren Sie eine Variable
var activeField: UITextField?
fügen Sie dann diese Methoden hinzu
func registerForKeyboardNotifications()
{
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications()
{
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification)
{
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.scrollEnabled = true
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeFieldPresent = activeField
{
if (!CGRectContainsPoint(aRect, activeField!.frame.Origin))
{
self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification)
{
//Once keyboard disappears, restore original positions
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.scrollEnabled = false
}
func textFieldDidBeginEditing(textField: UITextField!)
{
activeField = textField
}
func textFieldDidEndEditing(textField: UITextField!)
{
activeField = nil
}
Vergewissern Sie sich, dass Sie Ihren ViewController als UITextFieldDelegate
deklarieren und in Ihren Initialisierungsmethoden korrekte Delegaten festlegen: Ex:
self.you_text_field.delegate = self
Denken Sie daran, registerForKeyboardNotifications
bei viewInit und deregisterFromKeyboardNotifications
beim Beenden aufzurufen.
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
if (!aRect.contains(activeField.frame.Origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
@objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
Hier ist meine 2 Cent:
Haben Sie versucht: https://github.com/hackiftekhar/IQKeyboardManager
Sehr einfach zu installieren, Swift oder Objective-C.
Wie es funktioniert:
IQKeyboardManager (Swift): - IQKeyboardManagerSwift ist über CocoaPods verfügbar. Zur Installation fügen Sie einfach die folgende Zeile zu Ihrer Pod-Datei hinzu:
pod 'IQKeyboardManagerSwift'
Importieren Sie in AppDelegate.Swift einfach das IQKeyboardManagerSwift-Framework und aktivieren Sie IQKeyboardManager.
import IQKeyboardManagerSwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
IQKeyboardManager.sharedManager().enable = true
return true
}
}
Und das ist alles. Einfach!
Ich fand es perfekt, für mich zu arbeiten:
func textFieldDidBeginEditing(textField: UITextField) {
if textField == email || textField == password {
animateViewMoving(true, moveValue: 100)
}
}
func textFieldDidEndEditing(textField: UITextField) {
if textField == email || textField == password {
animateViewMoving(false, moveValue: 100)
}
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
let movementDuration:NSTimeInterval = 0.3
let movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations("animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
Sie können auch die Höhenwerte ändern. Entfernen Sie die "if-Anweisung", wenn Sie sie für alle Textfelder verwenden möchten.
Sie können dies sogar für alle Steuerelemente verwenden, für die eine Benutzereingabe erforderlich ist, z. B. TextView.
Gibt es eine Möglichkeit, den Bildschirm only zu verschieben, wenn die unteren Felder bearbeitet werden?
Ich hatte ein ähnliches Problem und fand eine ziemlich unkomplizierte Lösung ohne die Verwendung einer scrollView und stattdessen if-Anweisungen innerhalb der keyboardWillShow/Hide-Methoden.
func keyboardWillShow(notification: NSNotification) {
if bottomText.editing{
self.view.window?.frame.Origin.y = -1 * getKeyboardHeight(notification)
}
}
func keyboardWillHide(notification: NSNotification) {
if self.view.window?.frame.Origin.y != 0 {
self.view.window?.frame.Origin.y += getKeyboardHeight(notification)
}
}
Dies war eine gute Lösung für mich, da ich nur zwei Textfelder hatte.
Verschiebt die gesamte Ansicht nach oben: nur wenn bestimmte Textfelder (bottomText) bearbeitet werden
Verschiebt die gesamte Ansicht nach unten: nur, wenn sich die Ansicht nicht am ursprünglichen Ort befindet
Warum implementieren Sie dies nicht in einem UITableViewController? Die Tastatur blendet keine Textfelder aus, wenn sie angezeigt wird.
Verwenden Sie diese Erweiterung, um eine beliebige UIView zu verschieben, wenn die Tastatur angezeigt wird.
extension UIView {
func bindToKeyboard(){
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
@objc func keyboardWillChange(_ notification: NSNotification){
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = endFrame.Origin.y - beginningFrame.Origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.frame.Origin.y += deltaY
}, completion: nil)
}
}
Binden Sie dann in Ihrem viewdidload Ihre Ansicht an die Tastatur
UiView.bindToKeyboard()
Swift 4 (** aktualisiert ) mit Erweiterung **
inViewDidLoad
self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain
self.watchForKeyboard()
fügen Sie die folgende Erweiterung hinzu
import UIKit
private var xoAssociationKeyForBottomConstrainInVC: UInt8 = 0
extension UIViewController {
var containerDependOnKeyboardBottomConstrain :NSLayoutConstraint! {
get {
return objc_getAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC) as? NSLayoutConstraint
}
set(newValue) {
objc_setAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
func watchForKeyboard() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown(notification:)), name:UIResponder.keyboardWillShowNotification, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:UIResponder.keyboardWillHideNotification, object: nil);
}
@objc func keyboardWasShown(notification: NSNotification) {
let info = notification.userInfo!
let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.containerDependOnKeyboardBottomConstrain.constant = -keyboardFrame.height
self.view.layoutIfNeeded()
})
}
@objc func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.containerDependOnKeyboardBottomConstrain.constant = 0
self.view.layoutIfNeeded()
})
}
}
Ich verwende SwiftLint, das einige Probleme mit der Formatierung der akzeptierten Antwort hatte. Speziell:
kein Leerzeichen vor dem Doppelpunkt, kein Force Casting, bevorzugen UIEdgeInset (oben: etc ... anstelle von UIEdgeInsetMake.
hier also die Updates für Swift 3
func registerForKeyboardNotifications() {
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func deregisterFromKeyboardNotifications() {
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWasShown(notification: NSNotification) {
//Need to calculate keyboard exact size due to Apple suggestions
scrollView?.isScrollEnabled = true
var info = notification.userInfo!
if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
scrollView?.contentInset = contentInsets
scrollView?.scrollIndicatorInsets = contentInsets
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
if let activeField = self.activeField {
if !aRect.contains(activeField.frame.Origin) {
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
}
func keyboardWillBeHidden(notification: NSNotification) {
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize.height, right: 0.0)
scrollView?.contentInset = contentInsets
scrollView?.scrollIndicatorInsets = contentInsets
}
view.endEditing(true)
scrollView?.isScrollEnabled = false
}
func textFieldDidBeginEditing(_ textField: UITextField) {
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
activeField = nil
}
Ich denke, diese Klausel ist falsch:
if (!CGRectContainsPoint(aRect, activeField!.frame.Origin))
Während der Ursprung des activeField sich möglicherweise über der Tastatur befindet, wird der maxY möglicherweise nicht ...
Ich würde einen 'max'-Punkt für das activeField erstellen und überprüfen, ob dies in der Tastatur Rect ist.
für Swift 4.2.
Dies gilt für jedes Formular. Kein Scrollen erforderlich.
Mache ein variantes uitextfield
var clickedTextField = UITextField()
In Ihrer Ansicht hat die Last
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
Kennen Sie das angeklickte Textfeld. Wahrscheinlich haben Sie Textfelder auf dem gesamten Bildschirm.
func textFieldDidBeginEditing(_ textField: UITextField) {
clickedTextField = textField
}
Prüfen Sie, ob die Tastatur ein Textfeld abdeckt oder nicht.
@objc func keyboardWillShow(sender: NSNotification,_ textField : UITextField) {
if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if clickedTextField.frame.Origin.y > keyboardSize.Origin.y {
self.view.frame.Origin.y = keyboardSize.Origin.y - clickedTextField.center.y - 20
}
}
}
@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.Origin.y = 0
}
Kehren Sie zum Schließen der Tastatur zurück
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
UPDATE: NSNotification.Name.UIKeyboardWillShow & NSNotification.Name.UIKeyboardWillHide werden in UIResponder.keyboardWillShowNotification & UIResponder.keyboardWillHideNotification umbenannt.
Es gibt bereits großartige Antworten, aber dies ist eine andere Art, mit dieser Situation umzugehen (mit Swift 3x ):
Rufen Sie zunächst die folgende Methode in viewWillAppear()
auf.
func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Nehmen Sie nun eine IBOutlet
von UIView
s obersten Randbedingungen Ihrer UIViewcontroller
wie folgt: (hier ist die UIView
die Unteransicht von UIScrollView
, dh Sie sollten eine UIScrollView
für alle Ihre subViews
haben)
@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!
Und eine weitere Variable wie folgt und einen Delegaten hinzufügen, d. H. UITextFieldDelegate
:
var activeTextField = UITextField() //This is to keep the reference of UITextField currently active
Danach ist hier der magische Teil, den Sie einfach unter snippet einfügen:
func keyboardWasShown(_ notification: Notification) {
let keyboardInfo = notification.userInfo as NSDictionary?
//print(keyboardInfo!)
let keyboardFrameEnd: NSValue? = (keyboardInfo?.value(forKey: UIKeyboardFrameEndUserInfoKey) as? NSValue)
let keyboardFrameEndRect: CGRect? = keyboardFrameEnd?.cgRectValue
if activeTextField.frame.Origin.y + activeTextField.frame.size.height + 10 > (keyboardFrameEndRect?.Origin.y)! {
UIView.animate(withDuration: 0.3, delay: 0, options: .transitionFlipFromTop, animations: {() -> Void in
//code with animation
//Print some stuff to know what is actually happening
//print(self.activeTextField.frame.Origin.y)
//print(self.activeTextField.frame.size.height)
//print(self.activeTextField.frame.size.height)
self.loginViewTopConstraint.constant = -(self.activeTextField.frame.Origin.y + self.activeTextField.frame.size.height - (keyboardFrameEndRect?.Origin.y)!) - 30.0
self.view.layoutIfNeeded()
}, completion: {(_ finished: Bool) -> Void in
//code for completion
})
}
}
func keyboardWillBeHidden(_ notification: Notification) {
UIView.animate(withDuration: 0.3, animations: {() -> Void in
self.loginViewTopConstraint.constant = self.view.frame.Origin.y
self.view.layoutIfNeeded()
})
}
//MARK: textfield delegates
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
activeTextField = textField
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case YOUR_TEXTFIELD_ONE:
YOUR_TEXTFIELD_TWO.becomeFirstResponder()
break
case YOUR_TEXTFIELD_TWO:
YOUR_TEXTFIELD_THREE.becomeFirstResponder()
break
default:
textField.resignFirstResponder()
break
}
return true
}
Nun der letzte Ausschnitt:
//Remove Keyboard Observers
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Vergessen Sie nicht, Ihren UITextField
s in UIStoryboard
Delegaten zuzuweisen.
Viel Glück!
Swift 3 Syntax:
func textFieldDidBeginEditing(_ textField: UITextField) {
// add if for some desired textfields
animateViewMoving(up: true, moveValue: 100)
}
func textFieldDidEndEditing(_ textField: UITextField) {
// add if for some desired textfields
animateViewMoving(up: false, moveValue: 100)
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
textFieldDidEndEditing(_ textField: UITextField) {
let movementDuration:TimeInterval = 0.5
let movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations("animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
dies ist eine nette Methode, um zu bekommen, was Sie wollen Sie können für bestimmte Textfelder "if" -Bedingungen hinzufügen Dieser Typ funktioniert jedoch für alle ... Ich hoffe, es kann für alle nützlich sein
Im folgenden Beispiel schiebe ich die Ansicht nur nach oben, wenn ich mit dem Bearbeiten von txtLastName oder txtCity beginne. Ich habe die Variable keyboardActive erstellt, weil sich die Ansicht um 2x nach oben verschieben lässt, wenn ich in txtLastName und danach auf txtCity klicke.
Schauen Sie nach, ob es für Sie funktioniert.
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var txtFirstName: UITextField!
@IBOutlet weak var txtLastName: UITextField!
@IBOutlet weak var txtCity: UITextField!
var keyboardActive = false
override func viewDidLoad() {
super.viewDidLoad()
self.txtFirstName.delegate = self
self.txtLastName.delegate = self
self.txtCity.delegate = self
}
func textFieldDidBeginEditing(textField: UITextField) {
if textField != self.txtFirstName && keyboardActive == false {
self.view.frame.Origin.y -= 165
self.keyboardActive = true
}
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
if textField != self.txtFirstName && keyboardActive == true {
self.view.frame.Origin.y += 165
self.keyboardActive = false
}
return true
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
}
Hier ist meine Version, nachdem ich die Dokumentation von Apple und die vorherigen Beiträge gelesen habe. Mir ist aufgefallen, dass die Textansicht nicht behandelt wurde, wenn sie von der Tastatur abgedeckt wurde. Leider funktioniert die Dokumentation von Apple nicht, da aus irgendeinem Grund die Tastatur NACH dem textViewDidBeginEditing aufgerufen wird. Ich bin damit umgegangen, indem ich eine zentrale Methode aufgerufen habe, die prüft, ob die Tastatur angezeigt wird UND ob eine Textansicht oder ein Textfeld bearbeitet wird. Auf diese Weise wird der Prozess nur dann ausgelöst, wenn BEIDE Bedingungen vorliegen.
Ein weiterer Punkt bei textViews ist, dass ihre Höhe so bemessen sein kann, dass die Tastatur den unteren Teil der Textansicht abschneidet und nicht angepasst wird, wenn der obere linke Punkt des angezeigt wird. Der von mir geschriebene Code nimmt also den Bildschirm-referenzierten Bottom-Left-Punkt eines beliebigen TextView- oder TextFields und erkennt, ob er in die Bildschirmkoordinaten der präsentierten Tastatur fällt, was impliziert, dass die Tastatur einen Teil davon abdeckt.
let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.Origin.x, aRect.maxY))) {
// scroll textView/textField into view
}
Wenn Sie einen Navigationscontroller verwenden, setzt die Unterklasse auch die automatische Anpassung der Bildlaufansicht für Einfügungen auf "False".
self.automaticallyAdjustsScrollViewInsets = false
Es führt durch jedes TextView und jedes TextField, um die Delegierten für die Handhabung festzulegen
for view in self.view.subviews {
if view is UITextView {
let tv = view as! UITextView
tv.delegate = self
} else if view is UITextField {
let tf = view as! UITextField
tf.delegate = self
}
}
Setzen Sie Ihre Basisklasse einfach auf die hier erstellte Unterklasse, um Ergebnisse zu erhalten.
import UIKit
class ScrollingFormViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {
var activeFieldRect: CGRect?
var keyboardRect: CGRect?
var scrollView: UIScrollView!
override func viewDidLoad() {
self.automaticallyAdjustsScrollViewInsets = false
super.viewDidLoad()
// Do any additional setup after loading the view.
self.registerForKeyboardNotifications()
for view in self.view.subviews {
if view is UITextView {
let tv = view as! UITextView
tv.delegate = self
} else if view is UITextField {
let tf = view as! UITextField
tf.delegate = self
}
}
scrollView = UIScrollView(frame: self.view.frame)
scrollView.scrollEnabled = false
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.addSubview(self.view)
self.view = scrollView
}
override func viewDidLayoutSubviews() {
scrollView.sizeToFit()
scrollView.contentSize = scrollView.frame.size
super.viewDidLayoutSubviews()
}
deinit {
self.deregisterFromKeyboardNotifications()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func registerForKeyboardNotifications()
{
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications()
{
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification)
{
let info : NSDictionary = notification.userInfo!
keyboardRect = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
adjustForKeyboard()
}
func keyboardWillBeHidden(notification: NSNotification)
{
keyboardRect = nil
adjustForKeyboard()
}
func adjustForKeyboard() {
if keyboardRect != nil && activeFieldRect != nil {
let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.Origin.x, aRect.maxY)))
{
scrollView.scrollEnabled = true
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect!.size.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
scrollView.scrollRectToVisible(activeFieldRect!, animated: true)
}
} else {
let contentInsets : UIEdgeInsets = UIEdgeInsetsZero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
scrollView.scrollEnabled = false
}
}
func textViewDidBeginEditing(textView: UITextView) {
activeFieldRect = textView.frame
adjustForKeyboard()
}
func textViewDidEndEditing(textView: UITextView) {
activeFieldRect = nil
adjustForKeyboard()
}
func textFieldDidBeginEditing(textField: UITextField)
{
activeFieldRect = textField.frame
adjustForKeyboard()
}
func textFieldDidEndEditing(textField: UITextField)
{
activeFieldRect = nil
adjustForKeyboard()
}
}
Swift 4.2
Meine Lösung zentriert (vertikal) die Ansicht auf einem UITextField
, wenn sich ihre Position unter der Tastatur befindet.
Schritt 1: Erstellen Sie eine neue Swift-Datei und fügen Sie die Klasse _UIViewWithKeyboard
ein.
Schritt 2: Legen Sie im Interface Builder eine benutzerdefinierte Klasse für Ihre obersten UIView
-Werte fest.
import UIKit
class UIViewWithKeyboard: UIView {
@IBInspectable var offsetMultiplier: CGFloat = 0.75
private var keyboardHeight = 0 as CGFloat
private weak var activeTextField: UITextField?
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.textDidBeginEditing),
name: UITextField.textDidBeginEditingNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillShow),
name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillHide),
name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func textDidBeginEditing(_ notification: NSNotification) {
self.activeTextField = notification.object as? UITextField
}
@objc func keyboardWillShow(_ notification: Notification) {
if let frameValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
keyboardHeight = frameValue.cgRectValue.size.height
if let textField = self.activeTextField {
let offset = textField.frame.maxY < frame.maxY - keyboardHeight ? 0
: textField.frame.maxY - (frame.maxY - keyboardHeight) * offsetMultiplier
self.setView(offset: offset)
}
}
}
@objc func keyboardWillHide(_ notification: NSNotification) {
self.setView(offset: 0)
}
func setView(offset: CGFloat) {
UIView.animate(withDuration: 0.25) {
self.bounds.Origin.y = offset
}
}
}
Swift 3
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var edtEmail: UITextField!
@IBOutlet var bottomTextfieldConstrain: NSLayoutConstraint! // <- this guy is the constrain that connect the bottom of textField to lower object or bottom of page!
@IBAction func edtEmailEditingDidBegin(_ sender: Any) {
self.bottomTextfieldConstrain.constant = 200
let point = CGPoint(x: 0, y: 200)
scrollView.contentOffset = point
}
@IBAction func edtEmailEditingDidEnd(_ sender: Any) {
self.bottomTextfieldConstrain.constant = 50
}
Die akzeptierte Antwort ist nahezu perfekt. Aber ich muss UIKeyboardFrameEndUserInfoKey
anstelle von UIKeyboardFrameBeginUserInfoKey,
verwenden, da letztere die Tastaturhöhe 0 zurückgeben.
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
var point = activeField.frame.Origin
point.y += activeField.frame.size.height
if (!aRect.contains(point)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
Swift 4
Sie können sich mit der Tastatur und der Animation problemlos nach oben und unten bewegen UITextField
import UIKit
class ViewController: UIViewController {
@IBOutlet var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.resignFirstResponder()
}
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.Origin.y - curFrame.Origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.textField.frame.Origin.y+=deltaY
},completion: nil)
}
Swift 4 hat meine Lösung aktualisiert
mit Constraint-Animation auf der Tastatur ein-/ausblenden, genießen.
import Foundation
import UIKit
class PhoneController: UIViewController, UITextFieldDelegate{
var phoneLayoutYConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
phoneField.delegate = self
view.addSubview(phoneField)
NSLayoutConstraint.activate([phoneField.heightAnchor.constraint(equalToConstant: 50),
phoneField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
phoneField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
phoneField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)])
phoneLayoutYConstraint = NSLayoutConstraint(item: phoneField, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
phoneLayoutYConstraint?.isActive = true
}
let phoneField: UITextField = {
let text = UITextField()
text.translatesAutoresizingMaskIntoConstraints = false
text.keyboardType = .numberPad
text.font = UIFont.systemFont(ofSize: 30)
text.layer.cornerRadius = 5.0
text.layer.masksToBounds = true
text.layer.borderColor = UIColor.darkGray.cgColor
text.layer.borderWidth = 2.0
return text
}()
override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
}
func textFieldDidEndEditing(_ textField: UITextField) {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
@objc func handleKeyBoardNotification(_ notification: NSNotification) {
if let info = notification.userInfo {
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let isKeyBoardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow
var aRect : CGRect = self.phoneField.frame
aRect.size.height -= keyboardSize!.height
phoneLayoutYConstraint?.constant = isKeyBoardShowing ? -keyboardSize!.height : 0
UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (boo) in
})
}
}
}
Umgeschrieben für Swift 4.2
In ViewDidLoad ..
NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWasShown), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWillBeHidden), name: UIResponder.keyboardWillHideNotification, object: nil)
Restliche Funtions
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
if (!aRect.contains(activeField.frame.Origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
@objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
Zunächst deklarieren Sie eine Variable, um Ihr aktives UITextField zu identifizieren.
Schritt 1:-
Wie als var activeTextField: UITextField
?
Schritt 2: - Danach fügen Sie diese beiden Zeilen in viewDidLoad hinzu.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
Schritt 3:-
Definieren Sie nun diese beiden Methoden in Ihrer Controller-Klasse.
func keyboardWillShow(_ notification: NSNotification) {
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
if (!aRect.contains(activeField.frame.Origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
func keyboardWillHide(_ notification: NSNotification) {
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = true
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
Für Swift 4.2
Mit diesem Code können Sie das Moment der Y-Achse des Rahmens für eine bestimmte Bildschirmgröße des Geräts steuern.
PS: Dieser Code verschiebt den Frame basierend auf der Position von TextField nicht intelligent.
Erstellen Sie eine Erweiterung für UIDevice
extension UIDevice {
enum ScreenType: String {
case iPhone4_4S = "iPhone 4 or iPhone 4s"
case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6s, iPhone 7 or iPhone 8"
case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6s Plus, iPhone 7 Plus or iPhone 8 Plus"
case iPhoneX_Xs = "iPhone X, iPhone Xs"
case iPhoneXR = "iPhone XR"
case iPhoneXSMax = "iPhone Xs Max"
case unknown
}
var screenType: ScreenType {
switch UIScreen.main.nativeBounds.height {
case 960:
return .iPhone4_4S
case 1136:
return .iPhones_5_5s_5c_SE
case 1334:
return .iPhones_6_6s_7_8
case 1920, 2208:
return .iPhones_6Plus_6sPlus_7Plus_8Plus
case 1792:
return .iPhoneXR
case 2436:
return .iPhoneX_Xs
case 2688:
return .iPhoneXSMax
default:
return .unknown
}
}
}
NotificationObserver auf viewDidLoad hinzufügen
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
Auswahl
@objc func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
if self.view.frame.Origin.y == 0 {
switch (UIDevice.current.screenType.rawValue) {
case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
self.view.frame.Origin.y -= 210
case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
self.view.frame.Origin.y -= 110
case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
self.view.frame.Origin.y -= 80
case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
self.view.frame.Origin.y -= 70
case (UIDevice.ScreenType.iPhoneXR.rawValue):
self.view.frame.Origin.y -= 70
case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
self.view.frame.Origin.y -= 70
default:
self.view.frame.Origin.y -= 150
}
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
if self.view.frame.Origin.y != 0 {
switch (UIDevice.current.screenType.rawValue) {
case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
self.view.frame.Origin.y += 210
case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
self.view.frame.Origin.y += 110
case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
self.view.frame.Origin.y += 80
case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
self.view.frame.Origin.y += 70
case (UIDevice.ScreenType.iPhoneXR.rawValue):
self.view.frame.Origin.y += 70
case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
self.view.frame.Origin.y += 70
default:
self.view.frame.Origin.y += 150
}
}
}
}
"Ich habe vergessen zu erwähnen, dass ich neu bei Swift bin: (Was wäre die richtige Syntax, um dies zu überprüfen? (Wie erhalte ich den Feldnamen in dieser Funktion?)"
OK . Bestätigen Sie zuerst das UITextFieldDelegate-Protokoll
class YourClass:UITextFieldDelegate
Dann implementieren Sie die Funktion
func textFieldDidBeginEditing(textField: UITextField!) {
if textField == txtOne
{
println("TextOne")
}
if textField == txtTwo
{
println("TextTwo")
}
}
Beachten Sie, dass der richtige Ansatz darin besteht, eine Bildlaufansicht zu verwenden und die Ansicht, die nach oben/unten verschoben werden sollte, in die Bildlaufansicht zu verschieben und Tastaturereignisse entsprechend zu behandeln
Dieser Code wird in dem von Ihnen bearbeiteten Textfeld nach oben verschoben, sodass Sie es in Swift 3 anzeigen können. Für diese Antwort müssen Sie auch Ihre Ansicht als UITextFieldDelegate festlegen:
var moveValue: CGFloat!
var moved: Bool = false
var activeTextField = UITextField()
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
if moved == true{
self.animateViewMoving(up: false, moveValue: moveValue )
moved = false
}
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
let movementDuration:TimeInterval = 0.3
let movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations("animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
Und dann in viewDidLoad:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
Welche Aufrufe (außerhalb von viewDidLoad):
func keyboardWillShow(notification: Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardSize.height
if (view.frame.size.height-self.activeTextField.frame.Origin.y) - self.activeTextField.frame.size.height < keyboardHeight{
moveValue = keyboardHeight - ((view.frame.size.height-self.activeTextField.frame.Origin.y) - self.activeTextField.frame.size.height)
self.animateViewMoving(up: true, moveValue: moveValue )
moved = true
}
}
}