ios - поле - работа с клавиатурой swift




Как я могу заставить UITextField двигаться вверх, когда клавиатура присутствует? (20)

С iOS SDK:

У меня есть UIView с UITextField которые вызывают клавиатуру. Мне нужно это, чтобы иметь возможность:

  1. Разрешить прокрутку содержимого UIScrollView для просмотра других текстовых полей после поднятия клавиатуры

  2. Автоматически «прыгать» (путем прокрутки) или сокращения

Я знаю, что мне нужен UIScrollView . Я попытался изменить класс UIView на UIScrollView но я все еще не могу прокручивать текстовые поля вверх или вниз.

Нужен ли мне UIView и UIScrollView ? Один идет внутри другого?

Что необходимо реализовать, чтобы автоматически перейти к активному текстовому полю?

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

Примечание. UIView (или UIScrollView ), с которым я работаю, воспитывается на вкладке ( UITabBar ), которая должна функционировать как обычно.

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

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

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
                     scrollView.frame.origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
       scrollView.frame.origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

Тем не менее, это не автоматически «продвигается» или сосредотачивается на нижние текстовые поля в видимой области, что мне бы очень понравилось.


Для быстрых программистов:

Это сделает все для вас, просто поместите их в класс контроллера вида View и реализуйте UITextFieldDelegate на свой контроллер представления и установите делегат textField для self

textField.delegate = self // Setting delegate of your UITextField to self

Внедрить методы обратного вызова делегата:

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
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()
}

Здесь я нашел простейшее решение для обработки клавиатуры.

Вам нужно просто скопировать-вставить ниже пример кода и изменить текстовое поле или любое представление, которое вы хотите переместить вверх.

Шаг 1

Просто скопируйте пасту ниже двух методов в вашем контроллере

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void)deregisterFromKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

Шаг 2

регистрировать и отменить регистрацию уведомлений клавиатуры в viewWillAppear и viewWillDisappear соответственно.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self registerForKeyboardNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [self deregisterFromKeyboardNotifications];
    [super viewWillDisappear:animated];
}

Шаг 3

Здесь приходит часть души. Просто замените текстовое поле и измените высоту, сколько вы хотите двигаться вверх.

- (void)keyboardWasShown:(NSNotification *)notification
{
    NSDictionary* info = [notification userInfo];
    CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //you need replace your textfield instance here
    CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin;
    CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;

    CGRect visibleRect = self.view.frame;
    visibleRect.size.height -= currentKeyboardSize.height;

    if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
    {
        //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below

        CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height  + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification *)notification
{
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

Ссылка : ну, пожалуйста, оцените этот парень , который поделился этим красивым отрывом кода, чистым решением.

Надеюсь, это было бы очень полезно кому-то там.


В textFieldDidBeginEditting и в textFieldDidEndEditing вызовите функцию [self animateTextField:textField up:YES] следующим образом:

-(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 = -130; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

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

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

Надеюсь, этот код вам поможет.

В Swift 2

func animateTextField(textField: UITextField, up: Bool) 
{
     let movementDistance:CGFloat = -130
     let movementDuration: Double = 0.3

     var movement:CGFloat = 0
     if up 
     {
         movement = movementDistance
     }
     else 
     {
         movement = -movementDistance
     }
     UIView.beginAnimations("animateTextField", context: nil)
     UIView.setAnimationBeginsFromCurrentState(true)
     UIView.setAnimationDuration(movementDuration)
     self.view.frame = CGRectOffset(self.view.frame, 0, movement)
     UIView.commitAnimations()
}


func textFieldDidBeginEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:true)
}

func textFieldDidEndEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:false)
}

SWIFT 3

 func animateTextField(textField: UITextField, up: Bool)
    {
        let movementDistance:CGFloat = -130
        let movementDuration: Double = 0.3

        var movement:CGFloat = 0
        if up
        {
            movement = movementDistance
        }
        else
        {
            movement = -movementDistance
        }
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }


    func textFieldDidBeginEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:true)
    }

    func textFieldDidEndEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:false)
    }

Для универсального решения здесь был мой подход к реализации IQKeyboardManager .

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

Шаг 2: - Если найдено 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 вниз в соответствии с нарушенным расстоянием.

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

Это все, что IQKeyboardManager делаю для IQKeyboardManager с NO LINE OF CODE ! нужно только перетащить связанный исходный файл в проект. IQKeyboardManager также поддерживает ориентацию устройств , автоматическое управление UIToolbar , KeybkeyboardDistanceFromTextField и многое другое, чем вы думаете.


На самом деле лучше всего использовать реализацию Apple, как это предусмотрено в docs . Однако код, который они предоставляют, неисправен. Замените часть, найденную в keyboardWasShown: чуть ниже комментариев к следующему:

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

Проблемы с кодом Apple следующие: (1) Они всегда вычисляют, находится ли точка в кадре представления, но это ScrollView , поэтому она может уже прокручиваться, и вам нужно учитывать это смещение:

origin.y -= scrollView.contentOffset.y

(2) Они сдвигают contentOffset на высоту клавиатуры, но мы хотим наоборот (мы хотим сдвинуть contentOffset по высоте, которая видна на экране, а не в том, что нет):

activeField.frame.origin.y-(aRect.size.height)

У меня также возникла проблема с UIScrollView состоящим из нескольких UITextFields , из которых один или несколько из них будут закрыты клавиатурой при их редактировании.

Вот некоторые вещи, которые следует учитывать, если ваш UIScrollView неправильно прокручивается.

1) Убедитесь, что ваш contentSize больше размера кадра UIScrollView . Способ понять UIScrollViews состоит в том, что UIScrollView похож на окно просмотра содержимого, определенного в contentSize. Поэтому, когда для просмотра UIScrollview в любом месте, contentSize должен быть больше, чем UIScrollView . Кроме того, прокрутки не требуется, поскольку все, что определено в contentSize, уже видно. BTW, default contentSize = CGSizeZero .

2) Теперь, когда вы понимаете, что UIScrollView действительно является окном в вашем «контенте», способ обеспечить, чтобы клавиатура не скрывала ваше окно просмотра UIScrollView's было бы изменить размер UIScrollView чтобы при наличии клавиатуры вы имеют окно UIScrollView размер которого зависит от исходного кадра UIScrollView минус высота клавиатуры. Это гарантирует, что ваше окно будет только той небольшой видимой областью.

3) Вот улов: когда я впервые реализовал это, я решил, что мне нужно будет получить CGRect отредактированного UIScrollView's поля и вызвать метод scrollRecToVisible UIScrollView's . Я UITextFieldDelegate метод textFieldDidBeginEditing с вызовом метода scrollRecToVisible . Это действительно со странным побочным эффектом, что прокрутка будет привязать UITextField к позиции. В течение долгого времени я не мог понять, что это было. Затем я прокомментировал метод textFieldDidBeginEditing Delegate, и все это работает !! (???). Как оказалось, я считаю, что UIScrollView фактически неявно выводит UITextField отредактированный UITextField в видимое окно неявно. Моя реализация метода UITextFieldDelegate и последующего вызова scrollRecToVisible была избыточной и была причиной странного побочного эффекта.

Итак, вот шаги для правильной прокрутки вашего UITextField в UIScrollView на место, когда появляется клавиатура.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. Зарегистрировать для уведомлений клавиатуры в viewDidLoad
  2. Отменить viewDidUnload клавиатурных nofitications в viewDidUnload
  3. Убедитесь, что contentSize установлен и больше, чем ваш UIScrollView в viewDidLoad
  4. Сжимайте UIScrollView когда клавиатура присутствует
  5. Верните обратно UIScrollView когда клавиатура уйдет.
  6. Используйте ivar, чтобы определить, отображается ли клавиатура на экране, поскольку уведомления о клавиатуре отправляются каждый раз, когда UITextField имеет UITextField даже если клавиатура уже присутствует, чтобы избежать сокращения UIScrollView когда она уже сжата

Следует отметить, что UIKeyboardWillShowNotification будет срабатывать, даже если клавиатура уже находится на экране, когда вы UITextField другой UITextField . Я позаботился об этом, используя ivar, чтобы избежать изменения размера UIScrollView когда клавиатура уже находится на экране. Неожиданное изменение размера UIScrollView когда клавиатура уже там, будет катастрофической!

Надеюсь, что этот код избавит некоторых из вас от головной боли.


developer.apple.com/library/ios/#documentation/StringsTextFonts/… документе описывается решение этой проблемы. Посмотрите исходный код в разделе «Перемещение содержимого, находящегося под клавиатурой». Это довольно просто.

EDIT: Заметил, что в этом случае есть ошибка. Возможно, вы захотите слушать UIKeyboardWillHideNotificationвместо этого UIKeyboardDidHideNotification. В противном случае прокрутка позади клавиатуры будет обрезана на время анимации закрытия клавиатуры.


Swift 4 .

Вы можете легко перемещаться вверх и вниз UITextFieldили UIViewс UIKeyBoardпомощьюAnimation

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

    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
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

Примечание : этот ответ предполагает, что ваш textField находится в scrollView.

Я предпочитаю иметь дело с этим, используя scrollContentInset и scrollContentOffset вместо того, чтобы возиться с рамками моего представления.

Сначала давайте прослушаем уведомления о клавиатуре

//call this from viewWillAppear
-(void)addKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
    [[NSNotificationCenter default
    Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

Следующий шаг - сохранить свойство, представляющее текущего первого ответчика (UITextfield / UITextVIew, который в настоящее время имеет клавиатуру).

Мы используем методы делегата для установки этого свойства. Если вы используете другой компонент, вам понадобится нечто подобное.

Обратите внимание, что для текстового поля мы устанавливаем его в файле doBeginEditing и для textView в shouldBeginEditing. Это связано с тем, что textViewDidBeginEditing вызывается после UIKeyboardWillShowNotification по какой-то причине.

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
    self.currentFirstResponder = textView;
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    self.currentFirstResponder = textField;
}

Наконец, вот волшебство

- (void)keyboardWillShow:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];


    /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
    if(self.currentFirstResponder){

        //keyboard origin in currentFirstResponderFrame
        CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.origin fromView:nil];

        float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);

        //only scroll the scrollview if keyboard overlays the first responder
        if(spaceBetweenFirstResponderAndKeyboard>0){
            //if i call setContentOffset:animate:YES it behaves differently, not sure why
            [UIView animateWithDuration:0.25 animations:^{
                [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
            }];
        }
    }

    //set bottom inset to the keyboard height so you can still scroll the whole content

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;

}

- (void)keyboardWillHide:(NSNotification*)aNotification{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}

Просто используя TextFields:

1a) Использование Interface Builder : выберите All TextFields => Edit => Embed In => ScrollView

1b) Встраивание текстовых полей вручную в UIScrollView с именем scrollView

2) Установить UITextFieldDelegate

3) Установите каждый textField.delegate = self; (или сделать соединения в Interface Builder )

4) Копировать / Вставить:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}

Используйте эту третью сторону, вам не нужно писать даже одну строку

github.com/hackiftekhar/IQKeyboardManager

скачать проект и перетащить IQKeyboardManager в ваш проект. Если вы обнаружили какую-либо проблему, прочитайте документ README.

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

Спасибо и удачи!


Небольшое исправление, которое работает для многих UITextFields

#pragma mark UIKeyboard handling

#define kMin 150

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
   if (currTextField) {
      [currTextField release];
   }
   currTextField = [sender retain];
   //move the main view, so that the keyboard does not hide it.
   if (self.view.frame.origin.y + currTextField.frame.origin. y >= kMin) {
        [self setViewMovedUp:YES]; 
   }
}



//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
   [UIView beginAnimations:nil context:NULL];
   [UIView setAnimationDuration:0.3]; // if you want to slide up the view

   CGRect rect = self.view.frame;
   if (movedUp)
   {
      // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
      // 2. increase the size of the view so that the area behind the keyboard is covered up.
      rect.origin.y = kMin - currTextField.frame.origin.y ;
   }
   else
   {
      // revert back to the normal state.
      rect.origin.y = 0;
   }
   self.view.frame = rect;

   [UIView commitAnimations];
}


- (void)keyboardWillShow:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately

   if ([currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y >= kMin)
   {
      [self setViewMovedUp:YES];
   }
   else if (![currTextField isFirstResponder] && currTextField.frame.origin.y  + self.view.frame.origin.y < kMin)
   {
      [self setViewMovedUp:NO];
   }
}

- (void)keyboardWillHide:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
   if (self.view.frame.origin.y < 0 ) {
      [self setViewMovedUp:NO];
   }

}


- (void)viewWillAppear:(BOOL)animated
{
   // register for keyboard notifications
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) 
                                                name:UIKeyboardWillShowNotification object:self.view.window]; 
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) 
                                                name:UIKeyboardWillHideNotification object:self.view.window]; 
}

- (void)viewWillDisappear:(BOOL)animated
{
   // unregister for keyboard notifications while not visible.
   [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 
}

Это решение использует Swift.

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = 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.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}

попробуйте этот короткий трюк ...

 - (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 = textField.frame.origin.y / 2; // 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];
    }

Счастливое кодирование:) ....


Был поиск хорошего учебника для начинающих по теме, нашел лучший учебник here .

В приведенном ниже MIScrollView.hпримере учебника обязательно разместите

@property (nonatomic, retain) id backgroundTapDelegate;

как вы видите.


В соответствии с документами , начиная с iOS 3.0, UITableViewControllerкласс автоматически изменяет размеры и перетаскивает свой вид таблицы при редактировании текстовых полей. Я думаю, что этого недостаточно, чтобы помещать текстовое поле внутри, UITableViewCellкак указывали некоторые.

Из документов :

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


Для перемещения рамки просмотра не требуется просмотр прокрутки. Вы можете изменить рамку viewcontroller'sпредставления, чтобы весь вид перемещался настолько, чтобы помещать текстовое поле firstresponder над клавиатурой. Когда я столкнулся с этой проблемой, я создал подкласс, UIViewControllerкоторый делает это. Он замечает, что на клавиатуре появится уведомление и обнаружит первый ответчик subview и (при необходимости) он оживляет основной вид вверх настолько, чтобы первый ответчик находился выше клавиатуры. Когда клавиатура скрывается, она оживляет вид назад, где он был.

Чтобы использовать этот подкласс, сделайте свой пользовательский контроллер представлений подклассом GMKeyboardVC и наследует эту функцию (просто убедитесь, что вы реализуете, viewWillAppearи viewWillDisappearони должны вызвать супер). Класс находится на github .


Когда UITextFieldнаходится в UITableViewCellпрокруткой должен быть установлен автоматически.

Если это не так, возможно, из-за неправильного кода / настройки tableview.

Например, когда я перезагрузил свой длинный стол одним UITextFieldснизу следующим образом,

-(void) viewWillAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

то мое текстовое поле внизу было закрыто клавиатурой, которая появилась, когда я щелкнул внутри текстового поля.

Чтобы исправить это, я должен был сделать это -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}

Следует рассмотреть вопрос о том, хотите ли вы когда-либо использовать UITextFieldего самостоятельно. Я не сталкивался с любыми хорошо разработанными приложениями для iPhone, которые фактически используются UITextFieldsза пределами UITableViewCells.

Это будет какая-то дополнительная работа, но я рекомендую вам реализовать все представления ввода данных в виде таблиц. Добавьте UITextViewв свой UITableViewCells.


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

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

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

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

- (void)keyboardWillShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    activeField = nil;
}

-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

PS: Я надеюсь, что код поможет кому-то сделать желаемый эффект быстро. (Xcode 4.5)





uikeyboard