Как прокручивать UIScrollView при появлении клавиатуры?

У меня проблемы с моим кодом. Я пытаюсь переместить UIScrollView когда я редактирую UITextField который должен быть скрыт клавиатурой.

Сейчас я перемещаю основной фрейм, потому что не знаю, как «прокручивать» код. Итак, я немного поработал над кодом, он работает нормально, но когда я редактирую UItextfield, и я переключаюсь на другой UITextField не нажимая кнопку «возврат», основной вид идет waaayyyyy далеко вверх.

Я сделал NSLog() с моими переменными размером, расстоянием и textFieldRect.origin.y, как вы можете видеть ниже. Когда я помещаю два UITextField в одно и то же место (y origin), и я делаю этот особый «переключатель» (с нажатием на возврат), я получаю одинаковые числа, тогда как мой код работал отлично для первого редактирования UITextField но не для второго редактирования.

Проверь это:

 - (void)textFieldDidBeginEditing:(UITextField *)textField { { int size; CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField]; size = textFieldRect.origin.y + textFieldRect.size.height; if (change == FALSE) { size = size - distance; } if (size < PORTRAIT_KEYBOARD_HEIGHT) { distance = 0; } else if (size > PORTRAIT_KEYBOARD_HEIGHT) { distance = size - PORTRAIT_KEYBOARD_HEIGHT + 5; // +5 px for more visibility } NSLog(@"origin %f", textFieldRect.origin.y); NSLog(@"size %d", size); NSLog(@"distance %d", distance); CGRect viewFrame = self.view.frame; viewFrame.origin.y -= distance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrame]; [UIView commitAnimations]; change = FALSE; } - (void)textFieldDidEndEditing:(UITextField *)textField { change = TRUE; CGRect viewFrame = self.view.frame; viewFrame.origin.y += distance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrame]; [UIView commitAnimations]; } 

Есть идеи ?

19 Solutions collect form web for “Как прокручивать UIScrollView при появлении клавиатуры?”

Рекомендуемым способом от Apple является изменение contentInset UIScrollView . Это очень элегантное решение, потому что вам не нужно возиться с contentSize . Следующий код копируется из Руководства по программированию клавиатуры , где объясняется обработка этой проблемы. Вы должны изучить его.

 // Call this method somewhere in your view controller setup code. - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it's visible // Your application might not need or want this behavior. CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height; if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) { CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height); [scrollView setContentOffset:scrollPoint animated:YES]; } } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } 

Я только что реализовал это с Swift 2.0 для iOS9 на Xcode 7 (beta 6), отлично работает здесь.

 override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) registerKeyboardNotifications() } func registerKeyboardNotifications() { NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardWillShow(notification: NSNotification) { let userInfo: NSDictionary = notification.userInfo! let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0) scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets var viewRect = view.frame viewRect.size.height -= keyboardSize.height if CGRectContainsPoint(viewRect, textField.frame.origin) { let scrollPoint = CGPointMake(0, textField.frame.origin.y - keyboardSize.height) scrollView.setContentOffset(scrollPoint, animated: true) } } func keyboardWillHide(notification: NSNotification) { scrollView.contentInset = UIEdgeInsetsZero scrollView.scrollIndicatorInsets = UIEdgeInsetsZero } 

Отредактировано для Swift 3

Похоже, вам нужно только установить contentInset и scrollIndicatorInset с Swift 3, прокрутка / contentOffset выполняется автоматически.

 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) registerKeyboardNotifications() } func registerKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } func keyboardWillShow(notification: NSNotification) { let userInfo: NSDictionary = notification.userInfo! as NSDictionary let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue let keyboardSize = keyboardInfo.cgRectValue.size let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0) scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets } func keyboardWillHide(notification: NSNotification) { scrollView.contentInset = .zero scrollView.scrollIndicatorInsets = .zero } 

Все ответы здесь, похоже, забывают о ландшафтных возможностях. Если вы хотите, чтобы это работало, когда устройство повернуто к ландшафтному виду, вы столкнетесь с проблемами.

Трюк здесь в том, что, хотя представление известно о ориентации, клавиатура не работает. Это означает, что в плане ландшафта ширина клавиатуры фактически равна ее высоте и наоборот.

Чтобы изменить Яблоки рекомендуемый способ изменения вставки содержимого и получить поддержку ландшафтной ориентации, я бы рекомендовал использовать следующее:

 // Call this method somewhere in your view controller setup code. - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) { CGSize origKeySize = keyboardSize; keyboardSize.height = origKeySize.width; keyboardSize.width = origKeySize.height; } UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0); scroller.contentInset = contentInsets; scroller.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it's visible // Your application might not need or want this behavior. CGRect rect = scroller.frame; rect.size.height -= keyboardSize.height; NSLog(@"Rect Size Height: %f", rect.size.height); if (!CGRectContainsPoint(rect, activeField.frame.origin)) { CGPoint point = CGPointMake(0, activeField.frame.origin.y - keyboardSize.height); NSLog(@"Point Height: %f", point.y); [scroller setContentOffset:point animated:YES]; } } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } 

Здесь нужно обратить внимание на следующее:

 UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) { CGSize origKeySize = keyboardSize; keyboardSize.height = origKeySize.width; keyboardSize.width = origKeySize.height; } 

Что происходит, определяет, в какой ориентации находится устройство. Если это пейзаж, он будет «менять» значения ширины и высоты переменной keyboardSize, чтобы гарантировать, что правильные значения используются в каждой ориентации.

Для этого не нужно много кодировать, это очень легко, как ниже кода:

ваш весь текст в UIScrollview от nib, как показано на рисунке: –

введите описание изображения здесь

YourViewController.h

 @interface cntrInquiryViewController : UIViewController<UIScrollViewDelegate,UITextFieldDelegate> { IBOutlet UITextField *txtName; IBOutlet UITextField *txtEmail; IBOutlet UIScrollView *srcScrollView; } @end 

подключите IBOutlet от nib, а также соедините каждого делегата из UItextfiled и делегата scrollview от NIB

 -(void)viewWillAppear:(BOOL)animated { srcScrollView.contentSize = CGSizeMake(320, 500); [super viewWillAppear:YES]; } -(void)textFieldDidBeginEditing:(FMTextField *)textField { [srcScrollView setContentOffset:CGPointMake(0,textField.center.y-140) animated:YES];//you can set your y cordinate as your req also } -(BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; [srcScrollView setContentOffset:CGPointMake(0,0) animated:YES]; return YES; } 

ПРИМЕЧАНИЕ, если текстовый делегат не подключен, то никто не работает, пожалуйста, убедитесь, что все подключенные iBOulate и делегат правильно подключены

Рекомендация Apple перекодирована в Swift + Использование UIScrollView с автоматической компоновкой в ​​iOS (на основе следующих ссылок: ссылка 1 , ссылка 2 , ссылка 3 ):

 import UIKit class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet var t1: UITextField! @IBOutlet var t2: UITextField! @IBOutlet var t3: UITextField! @IBOutlet var t4: UITextField! @IBOutlet var srcScrollView: UIScrollView! @IBOutlet var contentView: UIView! var contentViewCoordinates: CGPoint! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. /* Constraints on content view */ let leftConstraint = NSLayoutConstraint(item:self.contentView, attribute:NSLayoutAttribute.Leading, relatedBy:NSLayoutRelation.Equal, toItem:self.view, attribute:NSLayoutAttribute.Left, multiplier:1.0, constant:0) self.view.addConstraint(leftConstraint) let rightConstraint = NSLayoutConstraint(item:self.contentView, attribute:NSLayoutAttribute.Trailing, relatedBy:NSLayoutRelation.Equal, toItem:self.view, attribute:NSLayoutAttribute.Right, multiplier:1.0, constant:0) self.view.addConstraint(rightConstraint) /* Tap gesture */ let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard") // prevents the scroll view from swallowing up the touch event of child buttons tapGesture.cancelsTouchesInView = false srcScrollView.addGestureRecognizer(tapGesture) /* Save content view coordinates */ contentViewCoordinates = contentView.frame.origin } func hideKeyboard() { t1.resignFirstResponder() t2.resignFirstResponder() t3.resignFirstResponder() t4.resignFirstResponder() } var activeField: UITextField? func textFieldDidBeginEditing(textField: UITextField) { activeField = textField } func textFieldDidEndEditing(textField: UITextField) { activeField = nil } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let center = NSNotificationCenter.defaultCenter() center.addObserver(self, selector: "keyboardOnScreen:", name: UIKeyboardDidShowNotification, object: nil) center.addObserver(self, selector: "keyboardOffScreen:", name: UIKeyboardDidHideNotification, object: nil) } func keyboardOnScreen(notification: NSNotification){ // Retrieve the size and top margin (inset is the fancy word used by Apple) // of the keyboard displayed. let info: NSDictionary = notification.userInfo! let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize!.height, 0.0) srcScrollView.contentInset = contentInsets srcScrollView.scrollIndicatorInsets = contentInsets var aRect: CGRect = self.view.frame aRect.size.height -= kbSize!.height //you may not need to scroll, see if the active field is already visible if (CGRectContainsPoint(aRect, activeField!.frame.origin) == false) { let scrollPoint:CGPoint = CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height) srcScrollView.setContentOffset(scrollPoint, animated: true) } } // func keyboardOnScreen(aNotification: NSNotification) { // let info: NSDictionary = aNotification.userInfo! // let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size // // var bkgndRect: CGRect! = activeField?.superview?.frame // // bkgndRect.size.height += kbSize!.height // // activeField?.superview?.frame = bkgndRect // // srcScrollView.setContentOffset(CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height), animated: true) // } func keyboardOffScreen(notification: NSNotification){ let contentInsets:UIEdgeInsets = UIEdgeInsetsZero srcScrollView.contentInset = contentInsets srcScrollView.scrollIndicatorInsets = contentInsets self.srcScrollView.setContentOffset(CGPointMake(0, -self.view.frame.origin.y/2), animated: true) } } 

Единственное, что я бы обновил в коде Apple, это метод keyboardWillBeHidden: для обеспечения плавного перехода.

 // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; [UIView animateWithDuration:0.4 animations:^{ self.scrollView.contentInset = contentInsets; }]; self.scrollView.scrollIndicatorInsets = contentInsets; } 

Я нашел, что вышеупомянутые ответы устарели. Также не идеальна при прокрутке.

Вот быстрая версия.

Он будет прокручиваться прямо под текстовым полем, без запасного пространства. И Он восстановится так, как это было похоже на его первое появление.

 //add observer override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidHide(_:)), name: UIKeyboardDidHideNotification, object: nil) } func keyboardDidShow(notification: NSNotification) { let userInfo: NSDictionary = notification.userInfo! let keyboardSize = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)!.CGRectValue.size let difference = keyboardSize.height - (self.view.frame.height - inputTextField.frame.origin.y - inputTextField.frame.size.height) if difference > 0 { var contentInset:UIEdgeInsets = self.scrollView.contentInset contentInset.bottom = difference self.scrollView.contentInset = contentInset let scrollPoint = CGPointMake(0, difference) self.scrollView.setContentOffset(scrollPoint, animated: true) } } func keyboardDidHide(notification: NSNotification) { let contentInset:UIEdgeInsets = UIEdgeInsetsZero self.scrollView.contentInset = contentInset } //remove observer deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } 

Ниже приведен ответ, совместимый с Swift 3 , который также будет работать с контроллерами представлений в контроллере навигации, поскольку они contentInset.top свойство contentInset.top прокруткиInset.top.

 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.registerKeyboardNotifications() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.unregisterKeyboardNotifications() } func registerKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardDidShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func unregisterKeyboardNotifications() { NotificationCenter.default.removeObserver(self) } func keyboardDidShow(notification: NSNotification) { let userInfo: NSDictionary = notification.userInfo! as NSDictionary let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue let keyboardSize = keyboardInfo.cgRectValue.size // Get the existing contentInset for the scrollView and set the bottom property to be the height of the keyboard var contentInset = self.scrollView.contentInset contentInset.bottom = keyboardSize.height self.scrollView.contentInset = contentInset self.scrollView.scrollIndicatorInsets = contentInset } func keyboardWillHide(notification: NSNotification) { var contentInset = self.scrollView.contentInset contentInset.bottom = 0 self.scrollView.contentInset = contentInset self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero } 

Это то, что я использовал. Это просто и хорошо работает.

 #pragma mark - Scrolling -(void)scrollElement:(UIView *)view toPoint:(float)y { CGRect theFrame = view.frame; float orig_y = theFrame.origin.y; float diff = y - orig_y; if (diff < 0) [self scrollToY:diff]; else [self scrollToY:0]; } -(void)scrollToY:(float)y { [UIView animateWithDuration:0.3f animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.view.transform = CGAffineTransformMakeTranslation(0, y); }]; } 

Используйте UITextField делегата textFieldDidBeginEditing: чтобы переместить вид вверх, а также добавить наблюдателя уведомлений, чтобы вернуть представление в нормальное состояние при textFieldDidBeginEditing: клавиатуры:

 -(void)textFieldDidBeginEditing:(UITextField *)textField { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; if (self.view.frame.origin.y == 0) [self scrollToY:-90.0]; // y can be changed to your liking } -(void)keyboardWillHide:(NSNotification*)note { [self scrollToY:0]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } 

Это последний код с улучшениями в Swift

  //MARK: UITextFieldDelegate func textFieldDidBeginEditing(textField: UITextField!) { //delegate method self.textField = textField } func textFieldShouldReturn(textField: UITextField!) -> Bool { //delegate method textField.resignFirstResponder() return true } //MARK: Keyboard handling override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) unregisterKeyboardNotifications() } func registerKeyboardNotifications() { NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) } func unregisterKeyboardNotifications() { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardDidShow(notification: NSNotification) { let userInfo: NSDictionary = notification.userInfo! let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0) scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets var viewRect = self.view.frame viewRect.size.height -= keyboardSize.height let relativeFieldFrame: CGRect = textField.convertRect(textField.frame, toView: self.view) if CGRectContainsPoint(viewRect, relativeFieldFrame.origin) { let scrollPoint = CGPointMake(0, relativeFieldFrame.origin.y - keyboardSize.height) scrollView.setContentOffset(scrollPoint, animated: true) } } func keyboardWillHide(notification: NSNotification) { scrollView.contentInset = UIEdgeInsetsZero scrollView.scrollIndicatorInsets = UIEdgeInsetsZero } 

Я бы сделал это вот так. Это много кода, но он гарантирует, что textField, находящийся в настоящее время в фокусе, вертикально центрируется в «доступном пространстве»:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)notification { NSDictionary *info = [notification userInfo]; NSValue *keyBoardEndFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey]; CGSize keyboardSize = [keyBoardEndFrame CGRectValue].size; self.keyboardSize = keyboardSize; [self adjustScrollViewOffsetToCenterTextField:self.currentTextField]; } - (void)keyboardWillHide:(NSNotification *)notification { self.keyboardSize = CGSizeZero; } - (IBAction)textFieldGotFocus:(UITextField *)sender { sender.inputAccessoryView = self.keyboardAccessoryView; self.currentTextField = sender; [self adjustScrollViewOffsetToCenterTextField:sender]; } - (void)adjustScrollViewOffsetToCenterTextField:(UITextField *)textField { CGRect textFieldFrame = textField.frame; float keyboardHeight = MIN(self.keyboardSize.width, self.keyboardSize.height); float visibleScrollViewHeight = self.scrollView.frame.size.height - keyboardHeight; float offsetInScrollViewCoords = (visibleScrollViewHeight / 2) - (textFieldFrame.size.height / 2); float scrollViewOffset = textFieldFrame.origin.y - offsetInScrollViewCoords; [UIView animateWithDuration:.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, scrollViewOffset); }completion:NULL]; } you'll need these two properties in your @interface... @property (nonatomic, assign) CGSize keyboardSize; @property (nonatomic, strong) UITextField *currentTextField; 

Обратите внимание, что действие - (IBAction)textFieldGotFocus: действие подключается к DidBeginEditing состоянию DidBeginEditing каждого текстового DidBeginEditing .

Также было бы немного лучше получить продолжительность анимации из уведомления о клавиатуре и использовать ее для анимации scrollview вместо фиксированного значения, но суди меня, это было достаточно для меня;)

Для этого вам не нужен UIScrollView. Я использовал этот код, и он работает для меня:

 -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField { if (textField==_myTextField) { [self keyBoardAppeared]; } return true; } -(void)textFieldDidEndEditing:(UITextField *)textField { if (textField==_myTextField) { [self keyBoardDisappeared]; } } -(void) keyBoardAppeared { CGRect frame = self.view.frame; [UIView animateWithDuration:0.3 delay:0 options: UIViewAnimationCurveEaseOut animations:^{ self.view.frame = CGRectMake(frame.origin.x, frame.origin.y-215, frame.size.width, frame.size.height); } completion:^(BOOL finished){ }]; } -(void) keyBoardDisappeared { CGRect frame = self.view.frame; [UIView animateWithDuration:0.3 delay:0 options: UIViewAnimationCurveEaseOut animations:^{ self.view.frame = CGRectMake(frame.origin.x, frame.origin.y+215, frame.size.width, frame.size.height); } completion:^(BOOL finished){ }]; } 

Вы можете прокручивать, используя свойство contentOffset в UIScrollView , например,

 CGPoint offset = scrollview.contentOffset; offset.y -= KEYBOARD_HEIGHT + 5; scrollview.contentOffset = offset; 

Существует также способ сделать анимированную прокрутку.

Что касается причины, по которой ваше второе редактирование не прокручивается правильно, это может быть связано с тем, что вы, кажется, предполагаете, что при каждом редактировании будет появляться новая клавиатура. Вы можете попробовать проверить, настроили ли вы уже видимую позицию «клавиатуры» (а также проверить видимость клавиатуры на данный момент, прежде чем возвращать ее).

Лучшим решением может быть прослушивание уведомления клавиатуры, например:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 

Я знаю, что это старый вопрос, но я подумал, что это может помочь другим. Я хотел, чтобы кое-что было немного легче реализовать для нескольких приложений, которые у меня были, поэтому я сделал класс для этого. Вы можете скачать его здесь, если хотите: https://github.com/sdernley/iOSTextFieldHandler

Это так же просто, как установить для всех UITextFields делегат себя

 textfieldname.delegate = self; 

Затем добавьте это в свой контроллер просмотра с именем вашей кнопки scrollView и submit

 - (void)textFieldDidBeginEditing:(UITextField *)textField { [iOSTextFieldHandler TextboxKeyboardMover:containingScrollView tf:textField btn:btnSubmit]; } 

Ниже приведены мои решения, которые работают (5 шагов)

Шаг 1: добавьте наблюдателя, чтобы поймать UITEXTFIELD или UITEXTVIEW ShoudBeginEditing (где объект включен или ViewDidLoad.

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateActiveField:) name:@"UPDATE_ACTIVE_FIELD" object:nil]; 

Шаг 2: отправьте уведомление, когда ..ShouldBeginEditing с OBJECT UITEXTFIELD или UITEXTVIEW

 -(BOOL)textViewShouldBeginEditing:(UITextView *)textView { [[NSNotificationCenter defaultCenter] postNotificationName:@"UPDATE_ACTIVE_FIELD" object:textView]; return YES; } 

Шаг 3: метод, который (Step1 calles) назначает текущий UITEXTFIELD или UITEXTVIEW

 -(void) updateActiveField: (id) sender { activeField = [sender object]; } 

Шаг4: Добавить наблюдателя клавиатуры UIKeyboardWillShowNotification (то же самое, что и в шаге 1)

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; 

и метод:

 // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); _currentEdgeInsets = self.layoutPanel.contentInset; // store current insets to restore them later self.layoutPanel.contentInset = contentInsets; self.layoutPanel.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it's visible CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height; UIWindow *window = [[UIApplication sharedApplication] keyWindow]; CGPoint p = [activeField convertPoint:activeField.bounds.origin toView:window]; if (!CGRectContainsPoint(aRect, p) ) { CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y +kbSize.height); [self.layoutPanel setContentOffset:scrollPoint animated:YES]; self.layoutPanel.scrollEnabled = NO; } } 

Шаг 5: Добавить наблюдателя клавиатуры UIKeyboardWillHideNotification (то же место, что и шаг 1)

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; 

и метод:

 // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { self.layoutPanel.contentInset = _currentEdgeInsets; self.layoutPanel.scrollIndicatorInsets = _currentEdgeInsets; self.layoutPanel.scrollEnabled = YES; } 

Не забудьте удалить наблюдателей!

Используйте следующее расширение, если вы не хотите слишком много вычислять:

 func scrollSubviewToBeVisible(subview: UIView, animated: Bool) { let visibleFrame = UIEdgeInsetsInsetRect(self.bounds, self.contentInset) let subviewFrame = subview.convertRect(subview.bounds, toView: self) if (!CGRectContainsRect(visibleFrame, subviewFrame)) { self.scrollRectToVisible(subviewFrame, animated: animated) } } 

И, возможно, вы хотите, чтобы ваш UITextField всегда был виден:

 func textViewDidChange(textView: UITextView) { self.scrollView?.scrollSubviewToBeVisible(textView, animated: false) } 

Я использовал этот ответ, предоставленный Sudheer Palchuri https://stackoverflow.com/users/2873919/sudheer-palchuri https://stackoverflow.com/a/32583809/6193496

В ViewDidLoad зарегистрируйте уведомления:

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DetailsViewController.keyboardWillShow(_:)), name:UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DetailsViewController.keyboardWillHide(_:)), name:UIKeyboardWillHideNotification, object: nil) 

Добавьте ниже методы наблюдателя, которые выполняют автоматическую прокрутку при появлении клавиатуры.

 func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true } func keyboardWillShow(notification:NSNotification){ var userInfo = notification.userInfo! var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue() keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil) var contentInset:UIEdgeInsets = self.scrollView.contentInset contentInset.bottom = keyboardFrame.size.height self.scrollView.contentInset = contentInset } func keyboardWillHide(notification:NSNotification){ var contentInset:UIEdgeInsets = UIEdgeInsetsZero self.scrollView.contentInset = contentInset } 

Мое решение имеет 4 шага:
– Шаг 1: функция прослушивает, когда появляется клавиатура

 - (void)keyboardWasShown:(NSNotification *)notification { // Get the size of the keyboard. CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; //top: 64 for navigation bar, 0 for without navigation UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, keyboardSize.height, 0); _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; } 

– Шаг 2: функция прослушивает, когда клавиатура исчезает

 - (void)keyboardWillHide:(NSNotification *)notification { //top: 64 for navigatiob bar UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, 0, 0); [_editScrollView setContentInset: contentInsets]; [_editScrollView setScrollIndicatorInsets: contentInsets]; } 

– Шаг 3: добавьте эти функции в центр уведомлений:

 - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } 

– Шаг 4: удалите прослушиватель, когда контроллер просмотра исчезнет

 - (void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } 

Попробуйте этот код в Swift 3:

 override func viewDidAppear(_ animated: Bool) { setupViewResizerOnKeyboardShown() } func setupViewResizerOnKeyboardShown() { NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShowForResizing), name: Notification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHideForResizing), name: Notification.Name.UIKeyboardWillHide, object: nil) } func keyboardWillShowForResizing(notification: Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue, let window = self.view.window?.frame { // We're not just minusing the kb height from the view height because // the view could already have been resized for the keyboard before self.view.frame = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width: self.view.frame.width, height: window.origin.y + window.height - keyboardSize.height) } else { debugPrint("We're showing the keyboard and either the keyboard size or window is nil: panic widely.") } } func keyboardWillHideForResizing(notification: Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { let viewHeight = self.view.frame.height self.view.frame = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width: self.view.frame.width, height: viewHeight) //viewHeight + keyboardSize.height } else { debugPrint("We're about to hide the keyboard and the keyboard size is nil. Now is the rapture.") } } deinit { NotificationCenter.default.removeObserver(self) } 
  • Сортировка nsarray строк, не основанных на строках
  • Как определить, есть ли в текстовом поле текст, а не числовое значение?
  • Могу ли я использовать автозапуск, чтобы обеспечить различные ограничения для пейзажной и портретной ориентации?
  • Извлеките и измените точку, в которой touchUpInside меняет touchUpOutside
  • Кодировка символов в NSString
  • Как создать объект NSInvocation с помощью метода, который принимает указатель на объект в качестве аргумента
  • Как popToRoot на одной вкладке, когда пользователь находится на другой вкладке?
  • Как проверить ввод текстового поля в реальном времени?
  • Swift 3: UIScrollView и (отключение) распознавателей жестов
  • Клавиатура iOS 8 скрывает мое текстовое изображение
  • Скрытие клавиатуры нажатием кнопки?
  • Как добавить значок в строку состояния iphone / ipod?
  • Interesting Posts

    IOS Swift API Google, как настроить placePicker

    Почему .bounds] не возвращает полный размер экрана?

    Преобразование NSpoint и передача значений в CGRectMake

    Доступ к журналу вызовов возможен в ios 8?

    Таблица со многими столбцами ios swift

    UIView анимация с UIPanGestureRecognizer скорость слишком быстро (не замедляется)

    Как я могу узнать, реализует ли суперкласс также тот же метод, который реализуется моим подклассом?

    Блокировка полей в MFMailComposeViewController

    Apple значок значок значок при представлении

    – устарела, что перечисление дает такое же поведение, как и раньше?

    iOS – предупреждение о веб-просмотре: присвоение 'id <UIWebViewDelegate>' из несовместимого типа

    Ошибка компиляции iOS XCode: невозможно выполнить команду: Ошибка сегментации: 11

    Как запретить построителю интерфейса добавлять 20-процентное дополнение к содержимому subview?

    GameCenter и безопасность

    Дополнительная иконка в имени приложения / Lable

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.