Крышки клавиатуры iPhone UITextField - PullRequest
121 голосов
/ 08 августа 2009

У меня есть приложение, в котором в Интерфейсном Разработчике я установил UIView с текстовым полем в нижней части представления. Когда я запускаю приложение и пытаюсь ввести текст в это поле, клавиатура скользит вверх над полем, поэтому я не могу видеть, что я печатаю, пока я снова не скрою клавиатуру.

Кто-нибудь еще сталкивался с этой проблемой и нашел хороший способ ее решения без необходимости прокрутки родительского представления или перемещения текстового поля дальше вверх по экрану?

Ответы [ 18 ]

290 голосов
/ 08 августа 2009

Обычное решение - сдвинуть поле (и все, что над ним) с анимацией, а затем отступить, когда вы закончите. Возможно, вам придется поместить текстовое поле и некоторые другие элементы в другое представление и сдвинуть представление как единое целое. (Я называю эти вещи "плитами", как в "тектонических плитах", но это только я). Но вот общая идея, если вам не нужно фантазировать.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField: textField up: YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField: textField up: NO];
}

- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
    const int movementDistance = 80; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

    int movement = (up ? -movementDistance : movementDistance);

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}
38 голосов
/ 08 октября 2009

Это творило чудеса для меня Скользящие поля uitext

В частности, он имеет преимущество вычисления расстояния анимации слайда в зависимости от положения текстового поля.

28 голосов
/ 17 июля 2013

IQKeyboardManager сделайте это для вас с БЕЗ СТРОКИ КОДА , нужно только перетащить соответствующий исходный файл в проект. IQKeyboardManager также поддерживает Ориентация устройства , Автоматическое управление UIToolbar , клавиатураDistanceFromTextField и намного больше, чем вы думаете.

enter image description here

Вот схема управления: Control Flow Chart

Step1: - Добавлены глобальные уведомления UITextField, UITextView и UIKeyboard в одноэлементном классе. Я назвал это IQKeyboardManager .

Step2: - Если найдено UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification или UITextViewTextDidBeginEditingNotification уведомлений, попробуйте получить экземпляр topMostViewController из иерархии UIWindow.rootViewController. Для того, чтобы правильно раскрыть UITextField / UITextView на нем, необходимо отрегулировать кадр topMostViewController.view.

Шаг 3: - Расчетное ожидаемое расстояние перемещения topMostViewController.view относительно первого ответа UITextField / UITextView.

Шаг 4: - Перемещено topMostViewController.view.frame вверх / вниз в соответствии с ожидаемым расстоянием перемещения.

Шаг 5: - Если найдено уведомление UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification или UITextViewTextDidEndEditingNotification, попробуйте снова получить экземпляр topMostViewController из иерархии UIWindow.rootViewController.

Шаг 6: - Расчетное нарушенное расстояние topMostViewController.view, которое необходимо восстановить в исходное положение.

Шаг 7: - Восстановлен topMostViewController.view.frame вниз в соответствии с нарушенным расстоянием.

Step8: - Инстанцированный синглтон IQKeyboardManager Экземпляр класса при загрузке приложения, поэтому каждый UITextField / UITextView в приложении будет автоматически корректироваться в соответствии с ожидаемым расстоянием перемещения.

Вот и все

7 голосов
/ 12 февраля 2014

Как насчет официального решения: Перемещение контента, расположенного под клавиатурой

Настройка вашего контента обычно включает временное изменение размера одного или больше просмотров и расположение их так, чтобы текстовый объект оставался видимый. Самый простой способ управления текстовыми объектами с помощью клавиатуры встроить их в объект UIScrollView (или один из его подклассов как UITableView). Когда клавиатура отображается, все, что вам нужно сделать сбрасывает область содержимого вида прокрутки и прокручивает нужные текстовый объект в положение. Таким образом, в ответ на UIKeyboardDidShowNotification, ваш метод-обработчик будет делать следующее:

  1. Получить размер клавиатуры.
  2. Настройте нижнюю вставку содержимого представления прокрутки с помощью клавиатуры. высота.
  3. Прокрутка целевого текстового поля в поле зрения.
// 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 app might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}
7 голосов
/ 18 февраля 2012

Чтобы расширить ответ Amagrammer, вот пример класса:

LoginViewController.h

@interface LoginViewController : UIViewController <UITextFieldDelegate> {

}

@property (nonatomic, retain) IBOutlet UITextField    *emailTextField;
@property (nonatomic, retain) IBOutlet UITextField    *passwordTextField;

Обратите внимание, что мы реализуем UITextFieldDelegate

LoginViewController.m

@implementation LoginViewController
@synthesize emailTextField=_emailTextField;
@synthesize passwordTextField=_passwordTextField;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        //Register to receive an update when the app goes into the backround
        //It will call our "appEnteredBackground method
        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appEnteredBackground)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    }
    return self;
}


- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
    const int movementDistance = 80; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

    int movement = (up ? -movementDistance : movementDistance);

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField: textField up: YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField: textField up: NO];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}
//This is called when the app goes into the background.
//We must reset the responder because animations will not be saved
- (void)appEnteredBackground{
    [self.emailTextField resignFirstResponder];
    [self.passwordTextField resignFirstResponder];
}
7 голосов
/ 17 октября 2011

У меня такая же проблема в UITableView textField ячейках. Я решил эту проблему, реализовав следующий метод для прослушивания уведомлений клавиатуры.

Наблюдатель за уведомлениями здесь:

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

Обработайте это уведомление с помощью функции ниже:

(void)keyboardWasShown:(NSNotification*)aNotification 
(void)keyboardWillBeHidden:(NSNotification*)aNotification 
5 голосов
/ 19 августа 2011

Проверьте это. Нет хлопот для вас.

Это решение очень аккуратное. Все, что вам нужно сделать, это добавить свои текстовые поля в UIScrollView и изменить его класс на TPKeyboardAvoidingScollView, если вы используете раскадровки. Представление прокрутки расширено таким образом, что оно будет определять, когда клавиатура видна, и будет перемещаться над клавиатурой на разумном расстоянии. Это идеальное решение, потому что оно не зависит от вашего UIViewController. Все необходимое делается в вышеупомянутом классе. Спасибо Майклу Тайсону и всем остальным.

TPKeyboardAvoiding

5 голосов
/ 11 ноября 2015

Ниже приведена быстрая версия ответа Amagrammer. Кроме того, это вариант с использованием события UIKeyboardWillShowNotification, поскольку мне нужно было знать размер клавиатур, прежде чем перемещать представление в сторону.

var keyboardHeight:CGFloat = 0

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChange:", name: UIKeyboardWillShowNotification, object: nil)
}

func textFieldDidBeginEditing(textField: UITextField) {
    //keyboardWillChange (below) is used instead of textFieldDidBeginEditing because textFieldDidBeginEditing
    //is called before the UIKeyboardWillShowNotification necessary to determine the keyboard height.
}

func textFieldDidEndEditing(textField: UITextField) {
    animateTextField(false)
}

func animateTextField(textFieldUp:Bool) {
    let movementDistance:CGFloat = keyboardHeight
    let movementDuration = 0.3

    let movement:CGFloat = (textFieldUp ? -movementDistance : movementDistance)

    UIView.beginAnimations("anim", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)
    self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    UIView.commitAnimations()
}

func keyboardWillChange(notification:NSNotification) {
    let keyboardRect:CGRect = ((notification.userInfo![UIKeyboardFrameEndUserInfoKey])?.CGRectValue)!
    keyboardHeight = keyboardRect.height
    animateTextField(true)
}
4 голосов
/ 25 декабря 2009

Был отличный пошаговое руководство по редактированию текстовых полей без затемнения (ссылка теперь не работает, вот ссылка Wayback: https://web.archive.org/web/20091123074029/http://acts-as-geek.blogspot.com/2009/11/editing-textfields-without-obscuring.html). Показывает, как переместить существующий UIView на UIScrollView и для автоматической прокрутки при появлении клавиатуры.

Я немного обновил его, чтобы вычислить правильную высоту для UIScrollView, когда есть элементы управления (например, UITabBar) ниже UIScrollBar. Смотрите пост-обновление uiview .

2 голосов
/ 12 июня 2014

Вот решение с использованием Xcode5, iOS7:

Используйте UITextfieldDelegate и блоки анимации.

Это почти весь код для ViewController, но я хотел включить код делегата для тех, кто все еще незнаком с шаблоном делегата (как я). Я также включил код, чтобы скрыть клавиатуру, когда вы нажимаете в сторону от просмотра текста.

Вы можете перемещать представления (кнопки, текстовые поля и т. Д.) Так высоко, как вам хотелось бы, просто верните их на место (+100, а затем -100).

@interface ViewController () <UITextFieldDelegate>
@property (strong, nonatomic) IBOutlet UITextField *MyTextField;

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.MyTextField.delegate = self;

}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
      NSLog(@"text began editing");

      CGPoint MyPoint = self.MyTextField.center;

      [UIView animateWithDuration:0.3
                    animations:^{

                    self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y - 100);
                                }];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
     NSLog(@"text ENDED editing");

     CGPoint MyPoint = self.MyTextField.center;

     [UIView animateWithDuration:0.3
                 animations:^{

     self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y + 100);
                             }];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     [self.view endEditing:YES];
}
...