UITextField: переместить вид при появлении клавиатуры
В настоящее время я работаю над приложением для iPhone с одним представлением, которое имеет несколько UITextFields для ввода. Когда клавиатура отображается, она перекрывает нижние текстовые поля. Поэтому я добавил соответствующий textFieldDidBeginEditing:
метод, чтобы переместить вид вверх, который прекрасно работает:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if ( ( textField != inputAmount ) && ( textField != inputAge ) ) {
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= kOFFSET_FOR_KEYBOARD;
frame.size.height += kOFFSET_FOR_KEYBOARD;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
}
Этот метод проверяет, является ли источником сообщения одно из текстовых полей, видимых при отображении клавиатуры, и, если нет, перемещает представление вверх.
Я также добавил textFieldDidEndEnditing:
метод, который снова перемещает представление вниз (и обновляет некоторые объекты модели в соответствии с измененным вводом):
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ( ( textField != inputMenge ) && ( textField != inputAlter ) ) {
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += kOFFSET_FOR_KEYBOARD;
frame.size.height -= kOFFSET_FOR_KEYBOARD;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
// Additional Code
}
Однако это решение имеет простой недостаток: когда я заканчиваю редактировать одно из "скрытых" текстовых полей и касаюсь другого текстового поля, клавиатура исчезает, вид перемещается вниз, вид снова поднимается и клавиатура снова появляется.
Есть ли возможность предотвратить исчезновение и повторное появление клавиатуры между двумя правками ("скрытых" текстовых полей), чтобы представление перемещалось только тогда, когда выбранное текстовое поле изменится с того, которое будет скрыто клавиатурой, на то, которое не будет скрыто)?
6 ответов
Это решение основано на решении ComSubVie.
Преимущества:
- Поддерживает поворот устройства - работает для всех ориентаций;
- Он не жестко кодирует значения длительности и кривой анимации, он считывает их из уведомления клавиатуры;
- Он использует
UIKeyboardWillShowNotification
вместоUIKeyboardDidShowNotification
синхронизировать анимацию клавиатуры и настраиваемые действия; - Он не использует устаревший
UIKeyboardBoundsUserInfoKey
; - Он обрабатывает изменение размера клавиатуры из-за нажатия международной клавиши;
- Исправлена утечка памяти при отмене регистрации событий клавиатуры;
- Весь код обработки клавиатуры инкапсулирован в отдельный класс -
KBKeyboardHandler
; - Гибкость -
KBKeyboardHandler
класс может быть легко расширен / модифицирован, чтобы лучше соответствовать конкретным потребностям;
Ограничения:
- Работает на iOS 4 и выше, для небольших версий требуются небольшие модификации;
- Работает для приложений с одним
UIWindow
, Если вы используете несколько UIWindows, вам может потребоваться изменитьretrieveFrameFromNotification:
метод.
Использование:
Включите в ваш проект файлы KBKeyboardHandler.h, KBKeyboardHandler.m и KBKeyboardHandlerDelegate.h. Реализовать KBKeyboardHandlerDelegate
Протокол в вашем контроллере представления - он состоит из одного метода, который будет вызываться, когда клавиатура отображается, скрыта или изменяется ее размер. Создать экземпляр KBKeyboardHandler
и установить его делегат (как правило, самостоятельно). См образец MyViewController
ниже.
KBKeyboardHandler.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol KBKeyboardHandlerDelegate;
@interface KBKeyboardHandler : NSObject
- (id)init;
// Put 'weak' instead of 'assign' if you use ARC
@property(nonatomic, assign) id<KBKeyboardHandlerDelegate> delegate;
@property(nonatomic) CGRect frame;
@end
KBKeyboardHandler.m:
#import "KBKeyboardHandler.h"
#import "KBKeyboardHandlerDelegate.h"
@implementation KBKeyboardHandler
- (id)init
{
self = [super init];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@synthesize delegate;
@synthesize frame;
- (void)keyboardWillShow:(NSNotification *)notification
{
CGRect oldFrame = self.frame;
[self retrieveFrameFromNotification:notification];
if (oldFrame.size.height != self.frame.size.height)
{
CGSize delta = CGSizeMake(self.frame.size.width - oldFrame.size.width,
self.frame.size.height - oldFrame.size.height);
if (self.delegate)
[self notifySizeChanged:delta notification:notification];
}
}
- (void)keyboardWillHide:(NSNotification *)notification
{
if (self.frame.size.height > 0.0)
{
[self retrieveFrameFromNotification:notification];
CGSize delta = CGSizeMake(-self.frame.size.width, -self.frame.size.height);
if (self.delegate)
[self notifySizeChanged:delta notification:notification];
}
self.frame = CGRectZero;
}
- (void)retrieveFrameFromNotification:(NSNotification *)notification
{
CGRect keyboardRect;
[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
self.frame = [[UIApplication sharedApplication].keyWindow.rootViewController.view convertRect:keyboardRect fromView:nil];
}
- (void)notifySizeChanged:(CGSize)delta notification:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
UIViewAnimationOptions curve;
[[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];
NSTimeInterval duration;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];
void (^action)(void) = ^{
[self.delegate keyboardSizeChanged:delta];
};
[UIView animateWithDuration:duration
delay:0.0
options:curve
animations:action
completion:nil];
}
@end
KBKeyboardHandlerDelegate.h:
@protocol KBKeyboardHandlerDelegate
- (void)keyboardSizeChanged:(CGSize)delta;
@end
Пример MyViewController.h:
@interface MyViewController : UIViewController<KBKeyboardHandlerDelegate>
...
@end
Пример MyViewController.m:
@implementation MyViewController
{
KBKeyboardHandler *keyboard;
}
- (void)dealloc
{
keyboard.delegate = nil;
[keyboard release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
keyboard = [[KBKeyboardHandler alloc] init];
keyboard.delegate = self;
}
- (void)viewDidUnload
{
[super viewDidUnload];
keyboard.delegate = nil;
[keyboard release];
keyboard = nil;
}
- (void)keyboardSizeChanged:(CGSize)delta
{
// Resize / reposition your views here. All actions performed here
// will appear animated.
// delta is the difference between the previous size of the keyboard
// and the new one.
// For instance when the keyboard is shown,
// delta may has width=768, height=264,
// when the keyboard is hidden: width=-768, height=-264.
// Use keyboard.frame.size to get the real keyboard size.
// Sample:
CGRect frame = self.view.frame;
frame.size.height -= delta.height;
self.view.frame = frame;
}
ОБНОВЛЕНИЕ: Исправлено предупреждение iOS 7, спасибо @weienv.
Я только что решил эту проблему. Решение представляет собой комбинацию UIKeyboardDidShowNotification
а также UIKeyboardDidHideNotification
наблюдатель с вышеуказанным textFieldDidBeginEditing:
а также textFieldDidEndEditing:
методы.
Вам нужны три дополнительные переменные, одна для хранения текущего выбранного UITextField (который я назвал activeField), одна, чтобы указать, было ли перемещено текущее представление, и одна, чтобы указать, отображается ли клавиатура.
Вот как два UITextField
Методы делегата посмотрим теперь:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
activeField = nil;
// Additional Code
}
Когда представление загружено, создаются следующие два наблюдателя:
- (void)viewDidLoad {
// Additional Code
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
}
И соответствующие методы реализованы следующим образом:
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardShown )
return;
if ( ( activeField != inputAmount ) && ( activeField != inputAge ) ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardShown = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardShown = NO;
}
Этот код работает сейчас, как и ожидалось. Клавиатура отключается только при нажатии кнопки "Готово", в противном случае она остается видимой и вид не перемещается.
В качестве дополнительного примечания, я думаю, что можно получить animationDuration
динамически, задавая NSNotification
объект, так как я уже играл с похожим решением, но не получил его работать (что он делает сейчас).
Этот контроллер должен быть UITextView
Делегируйте и вы должны установить self.textview.delegate = self
в viewdidload
-(void) textViewDidBeginEditing:(UITextView *)textView
{
NSLog(@"%f",self.view.frame.origin.y);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y =frame.origin.y -204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void) textViewDidEndEditing:(UITextView *)textView
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y + 204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
Как я уже упоминал в этом ответе:
Я разработал платформу для решения этой проблемы лучше и опубликовал ее сейчас. Это не только для UITextField и UITextView, он работает для любого пользовательского UIView, который принимает протокол UITextInput, такой как UITextField и UITextView, и предлагает множество полезных функций. Вы можете установить его через Carthage, CocoaPods или Swift Package Manager.
ODScrollView - это просто UIScrollView, который автоматически перемещает редактируемые текстовые области, такие как UITextField и UITextView, по вертикали в зависимости от видимости клавиатуры, чтобы обеспечить лучший пользовательский интерфейс.
особенности
- Автоматически перемещает UIViews первого респондента, которые принимают протокол UITextInput, вверх / вниз, когда клавиатура появляется / исчезает, например UITextField, UITextView, UISearchTextField или любой пользовательский UIView, который принимает протокол UITextInput.
- Обратите внимание, что если кадр UITextInput НЕ соответствует оставшейся области между ODScrollView и клавиатурой, ODScrollView настраивает UITextInput на основе положения курсора, а не кадра. В таких случаях можно использовать функцию trackTextInputCursor. пример
Предел корректировки может применяться для каждого UITextInput отдельно для настройки направления регулировки.Top и.Bottom. 20 CGFloat по умолчанию.
Регулировка может быть включена / отключена для каждого UITextInput отдельно. по умолчанию true.
Направление настройки - .Top, .Center, .Bottom - может применяться для каждого UITextInput отдельно. .Bottom по умолчанию. пример
- Параметры настройки определяют, как настраивается ODScrollView..Всегда по умолчанию.
- .Всегда: ODScrollView всегда регулирует UITextInput, который помещается в любом месте ODScrollView, независимо от того, перекрывается ли UITextInput с отображаемой клавиатурой. пример
- .IfNeeded: ODScrollView регулирует UITextInput только в том случае, если он перекрывается с показанной клавиатурой. пример
- Помимо UIScrollView.keyboardDismissModes, клавиатуру можно закрыть, коснувшись UIView, который предоставляется ODScrollViewDelegate. После закрытия клавиатуры ODScrollView может вернуть исходное положение. по умолчанию nil и false. пример
Применение
1 - Первое, что вам нужно сделать, это правильно настроить ODScrollView и его представление содержимого. Поскольку ODScrollView - это просто UIScrollView, вы можете реализовать ODScrollView так же, как и для UIScrollView. Вам решать, создавать ODScrollView с помощью раскадровки или программно.
Если вы создаете ODScrollView программно, вы можете продолжить с шага 4.
Предлагаемый способ создания UIScrollView в раскадровке
- Ifyou are using Content Layout Guide and Frame Layout Guide:
1.1 - scrollView: Place UIScrollView anywhere you want to use.
1.2 - contentView: Place UIView inside scrollView.
1.3 - Set contentView's top, bottom, leading and trailing constraints to Content Layout Guide's constraints.
1.4 - Set contentView's width equal to Frame Layout Guide's width.
1.5 - Set contentView's height equal to Frame Layout Guide's height or set static height which is larger than scrollView's height.
1.6 - Build your UI inside contentView.
- Ifyou are NOT using Content Layout Guide and Frame Layout Guide:
1.1 - scrollView: Place UIScrollView anywhere you want to use.
1.2 - contentView: Place UIView inside scrollView.
1.3 - Set contentView's top, bottom, leading and trailing constraints to 0.
1.4 - Set contentView's width equal to scrollView's width.
1.5 - Set contentView's height equal to scrollView's superview's height or set static height which is larger than scrollView's height.
1.6 - Build your UI inside contentView.
2 - Измените класс scrollView с UIScrollView на ODScrollView в инспекторе удостоверений на Storyboard.
3 - Создайте IBOutlets для scrollView и contentView на ViewController.
4 - Вызовите следующие методы внутри ViewDidLoad() на ViewController:
override func viewDidLoad() {
super.viewDidLoad()
//ODScrollView setup
scrollView.registerContentView(contentView)
scrollView.odScrollViewDelegate = self
}
5 - Необязательно: вы все еще можете использовать функции UIScrollView:
override func viewDidLoad() {
super.viewDidLoad()
//ODScrollView setup
scrollView.registerContentView(contentView)
scrollView.odScrollViewDelegate = self
// UIScrollView setup
scrollView.delegate = self // UIScrollView Delegate
scrollView.keyboardDismissMode = .onDrag // UIScrollView keyboardDismissMode. Default is .none.
UITextView_inside_contentView.delegate = self
}
6 - Принять ODScrollViewDelegate из ViewController и выбрать параметры ODScrollView:
extension ViewController: ODScrollViewDelegate {
// MARK:- State Notifiers: are responsible for notifiying ViewController about what is going on while adjusting. You don't have to do anything ifyou don't need them.
// #Optional
// Notifies when the keyboard showed.
func keyboardDidShow(by scrollView: ODScrollView) {}
// #Optional
// Notifies before the UIScrollView adjustment.
func scrollAdjustmentWillBegin(by scrollView: ODScrollView) {}
// #Optional
// Notifies after the UIScrollView adjustment.
func scrollAdjustmentDidEnd(by scrollView: ODScrollView) {}
// #Optional
// Notifies when the keyboard hid.
func keyboardDidHide(by scrollView: ODScrollView) {}
// MARK:- Adjustment Settings
// #Optional
// Specifies the margin between UITextInput and ODScrollView's top or bottom constraint depending on AdjustmentDirection
func adjustmentMargin(for textInput: UITextInput, inside scrollView: ODScrollView) -> CGFloat {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return 20
} else {
return 40
}
}
// #Optional
// Specifies that whether adjustment is enabled or not for each UITextInput seperately.
func adjustmentEnabled(for textInput: UITextInput, inside scrollView: ODScrollView) -> Bool {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return true
} else {
return false
}
}
// Specifies adjustment direction for each UITextInput. It means that some of UITextInputs inside ODScrollView can be adjusted to the bottom, while others can be adjusted to center or top.
func adjustmentDirection(selected textInput: UITextInput, inside scrollView: ODScrollView) -> AdjustmentDirection {
if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
return .bottom
} else {
return .center
}
}
/**
- Always : ODScrollView always adjusts the UITextInput which is placed anywhere in the ODScrollView.
- IfNeeded : ODScrollView only adjusts the UITextInput if it overlaps with the shown keyboard.
*/
func adjustmentOption(for scrollView: ODScrollView) -> AdjustmentOption {
.Always
}
// MARK: - Hiding Keyboard Settings
/**
#Optional
Provides a view for tap gesture that hides keyboard.
By default, keyboard can be dismissed by keyboardDismissMode of UIScrollView.
keyboardDismissMode = .none
keyboardDismissMode = .onDrag
keyboardDismissMode = .interactive
Beside above settings:
- Returning UIView from this, lets you to hide the keyboard by tapping the UIView you provide, and also be able to use isResettingAdjustmentEnabled(for scrollView: ODScrollView) setting.
- Ifyou return nil instead of UIView object, It means that hiding the keyboard by tapping is disabled.
*/
func hideKeyboardByTappingToView(for scrollView: ODScrollView) -> UIView? {
self.view
}
/**
#Optional
Resets the scroll view offset - which is adjusted before - to beginning its position after keyboard hid by tapping to the provided UIView via hideKeyboardByTappingToView.
## IMPORTANT:
This feature requires a UIView that is provided by hideKeyboardByTappingToView().
*/
func isResettingAdjustmentEnabled(for scrollView: ODScrollView) -> Bool {
true
}
}
7 - Необязательно: вы можете настроить ODScrollView, когда курсор перекрывается с клавиатурой при вводе многострочного UITextInput. trackTextInputCursor(для UITextInput) должен вызываться функциями UITextInput, которые запускаются во время набора текста.
/**
## IMPORTANT:
This feature is not going to work unless textView is subView of _ODScrollView
*/
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
_ODScrollView.trackTextInputCursor(for textView)
return true
}
Write below code in your view controller. tbl is your table view.
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[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
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark - Keyboard Methods
-(void)keyboardWillShow:(NSNotification *)notification
{
// 375 × 667 ( 750 × 1334 ) iPhone 6
//414 × 736
CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
int H = [[UIScreen mainScreen] bounds].size.height - 64- 20 -keyboardRect.size.height;
[UIView animateWithDuration:0.5 animations:^{
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
}];
}
-(void)keyboardWillChangeFrame:(NSNotification *)notification
{
CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
// int H = IS_IPHONE_5?504-keyboardRect.size.height:416-keyboardRect.size.height;
int H = [[UIScreen mainScreen] bounds].size.height - 64- 20 -keyboardRect.size.height;
[UIView animateWithDuration:0.5 animations:^{
// scroll.frame = rect;
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
}];
}
-(void)keyboardWillHide:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
// scroll.frame = rect;
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, 0, tbl.contentInset.right);
}];
}
Я понял вашу проблему, просто сделайте простую вещь, просто дайте выход UIScrollview. установить уникальное свойство Tag для каждого текстового поля в представлении.
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
switch (textField.tag)
{
case 2: //can be your textfiled tag
{ CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-150);
//set figure y-150 as per your comfirt
[scrollview setContentOffset:scrollPoint animated:YES];
}break;
case 3:
{ CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-180);
//set figure y-180 as per your comfirt
[scrollview setContentOffset:scrollPoint animated:YES];
}break;
...
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
if(textField.tag==3){
[scrollview setContentOffset:CGPointZero animated:YES];
}
//set the last textfield when you want to disappear keyboard.
}
Довольно простое решение, работает со всеми размерами экрана
Сначала вы должны встроить свои UITextFields в UIScrollView. В моем случае у меня было несколько UITextFields и UITextView.
Затем вы должны наследовать от UITextFieldDelegate, UITextViewDelegate.
class SettingsVC: UIViewController, UITextFieldDelegate, UITextViewDelegate
Назначьте делегатов textfield и textview себе.
fullNameTextField.delegate = self
usernameTextField.delegate = self
websiteTextField.delegate = self
profileDescription.delegate = self
Затем используйте этот код:
var editingTextInput: UIView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardShown(notification:)),
name: NSNotification.Name.UIKeyboardDidShow,
object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
}
func keyboardShown(notification: NSNotification) {
if let infoKey = notification.userInfo?[UIKeyboardFrameEndUserInfoKey],
let rawFrame = (infoKey as AnyObject).cgRectValue {
let keyboardFrame = view.convert(rawFrame, to: view)
let editingTextInputFrame = self.editingTextInput.convert(self.editingTextInput.frame, to: view)
if editingTextInputFrame.maxY > keyboardFrame.minY{
let diff = keyboardFrame.minY - editingTextInputFrame.maxY
containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
}
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.editingTextInput = textField
}
func textViewDidBeginEditing(_ textView: UITextView) {
self.editingTextInput = textView
}
func textFieldDidEndEditing(_ textField: UITextField) {
containerScrollView.setContentOffset(CGPoint.zero, animated: true)
}
func textViewDidEndEditing(_ textView: UITextView) {
containerScrollView.setContentOffset(CGPoint.zero, animated: true)
}
Короче говоря, вы подписываетесь на уведомление UIKeyboardDidShow. Когда вы нажимаете на textField или textView, клавиатура отображается, и вы берете кадр клавиатуры и кадр элемента ввода, к которому вы прикоснулись. Преобразуйте их в систему координат viewController и сравните самую низкую точку входного элемента с самой высокой клавиатурой. Если нижняя часть элемента ниже самой высокой клавиатуры, то установите смещение containerScrollView на разницу между ними.
if editingTextInputFrame.maxY > keyboardFrame.minY{
let diff = keyboardFrame.minY - editingTextInputFrame.maxY
containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
}