Как я могу заставить UITextField двигаться вверх при наличии клавиатуры - при начале редактирования?

С iOS SDK:

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

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

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

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

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

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

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

Примечание: 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
}

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

+1665
источник поделиться
96 ответов

Вам нужно добавить программно скроллинг с определенным размером кадра. Вы должны добавить UIScrollViewDelegate в файл .h. Вы должны включить scrollview для того, что вам нужно написать в viewDidLoad().

scrollview.scrollEnabled=YES;
scrollview.delegate=self;

scrollview.frame = CGRectMake(x,y,width,height);
//---set the content size of the scroll view--- 

[scrollview setContentSize:CGSizeMake(height,width)];

Таким образом вы можете добавить свои значения x, y, width и height. Я думаю, это поможет вам.

+7
источник

Попробуйте следующее:

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:self.m_Sp_Contact])
    {
        [self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES];          
    }
}
+7
источник
другие ответы

Связанные вопросы


Похожие вопросы

Swift 2.0:

Добавьте UIScrollView и добавьте textFields вверху. Сделайте ссылки на раскадровку на VC.

@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var scrollView: UIScrollView!

Добавьте следующие методы: UITextFieldDelegate и UIScrollViewDelegate.

//MARK:- TEXTFIELD METHODS
    func textFieldShouldReturn(textField: UITextField) -> Bool {

        if(username.returnKeyType == UIReturnKeyType.Default) {
            password.becomeFirstResponder()
        }
        textField.resignFirstResponder()
        return true
    }
    func textFieldDidBeginEditing(textField: UITextField) {

        dispatch_async(dispatch_get_main_queue()) {

            let scrollPoint:CGPoint = CGPointMake(0,textField.frame.origin.y/4)
            self.scrollView!.setContentOffset(scrollPoint, animated: true);
        }
    }
    func textFieldShouldEndEditing(textField: UITextField) -> Bool {

        dispatch_async(dispatch_get_main_queue()) {
          UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) })
        }
        return true
    }
    override func touchesBegan(touches: Set<UITouch>,
        withEvent event: UIEvent?) {
            self.view.endEditing(true)
    }
    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.scrollView.scrollEnabled =  true

        dispatch_async(dispatch_get_main_queue()) {
            UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true)

            })
        }
    }
+7
источник

Вот бесплатная библиотека для обработки клавиатуры Keyboard-Handling-in-iPhone-Applications. Вам нужно написать только одну строку кода:

[AutoScroller addAutoScrollTo:scrollView];

Это замечательно для обработки клавиатуры в формах

+6
источник

Я думаю, что лучший подход - использовать протокол-ориентированное программирование, если вы используете Swift.

Прежде всего, вы должны создать протокол KeyboardCapable, который дает любому UIViewController, соответствующему ему возможность регистрировать и отменить регистрацию наблюдателей на клавиатуре:

import Foundation
import UIKit

protocol KeyboardCapable: KeyboardAnimatable {
    func keyboardWillShow(notification: NSNotification)
    func keyboardWillHide(notification: NSNotification)
}

extension KeyboardCapable where Self: UIViewController {
    func registerKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }
}

Вы заметили постороннее ключевое слово KeyboardAnimatable на вышеуказанной части кода. Это просто имя следующего протокола, который нам нужно создать:

import Foundation
import UIKit

protocol KeyboardAnimatable {

}

extension KeyboardAnimatable where Self: UIViewController {
    func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.origin.x, -height, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }

    func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.origin.x, 0.0, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }
}

Этот протокол KeyboardAnimatable предоставляет всем UIViewController соответствующие ему два метода, которые будут анимировать весь вид вверх и вниз соответственно.

Итак, если KeyboardCapable соответствует KeyboardAnimatable, все UIViewController, соответствующие KeyboardCapable, также соответствуют KeyboardAnimatable. Это круто.

Посмотрите на UIViewController, соответствующий KeyboardCapable, и реагируя на события клавиатуры:

import Foundation
import UIKit

class TransferConfirmViewController: UIViewController, KeyboardCapable {
    //MARK: - LIFE CYCLE       
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        registerKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        unregisterKeyboardNotifications()
    }

    //MARK: - NOTIFICATIONS
    //MARK: Keyboard
    func keyboardWillShow(notification: NSNotification) {
        let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration)
    }

    func keyboardWillHide(notification: NSNotification) {
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardHideFullViewAnimation(withDuration: animationDuration)
    }
}

Теперь ваш UIViewController будет реагировать на события клавиатуры и будет оживлять в последствии.

Примечание. Если вы хотите создать пользовательскую анимацию вместо того, чтобы нажимать или вытягивать представление, вы должны определить пользовательские методы в протоколе KeyboardAnimatable или выполнить их в функциях KeyboardCapable. Это зависит от вас.

+6
источник

Просто добавьте это в ваш файл pod → pod 'IQKeyboardManager'

Вот и все, обрабатывает все клавиатуры, прокрутки и все!

Вам не нужно ничего кодировать, не может найти лучшего решения!

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

Он также имеет пользовательскую кнопку "Готово", которую можно удалить.

Ссылка → https://github.com/hackiftekhar/IQKeyboardManager

+6
источник

Гораздо более элегантным решением является использование подкласса UIView (хотя это не всегда уместно) и пересчет всех ваших подзонов при изменении родительского фрейма (и быть умным: только пересчитать их, если новый размер кадра изменилось, т.е. используйте CGRectEqualToRect для сравнения нового фрейма при переопределении setFrame и до того, как вы вызываете [super setFrame:frame_]). Единственный улов в этом заключается в том, что UIViewController, который вы собираетесь использовать, должен, вероятно, прослушивать события клавиатуры (или вы могли бы сделать это в самом UIView, для удобной инкапсуляции). Но только UIKeyboardWillShowNotification и UIKeyboardWillHideNotification. Это просто так, что он будет выглядеть гладко (если вы ждете, когда CG назовет его, вы получите момент неряшливости).

Это имеет преимущество при построении подкласса UIView, который делает все правильно. Во всяком случае.

Наивная реализация будет заключаться в переопределении drawRect: (do not), тем лучше будет просто использовать layoutSubviews (а затем в UIViewController или еще что вы можете вызвать [view setNeedsLayout] в SINGLE-методе, который вызывается для show или hide).

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

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

Приветствия.

+5
источник

Вот моя версия с использованием autolayout:

Идея состоит в том, чтобы просто встроить ваше представление, содержащее текстовые поля/текстовое представление, в UIScrollView, установить ограничение снизу к его суперпредставлению, создать выход и обновить его постоянным в соответствии с высотой клавиатуры с помощью уведомлений. Это основано на примере Apple здесь и технической заметке Apple по UIScrollView с использованием AutoLayout здесь.

1) Внедрите свой View V в UIScrollView S: если вы уже установили свои константы и подпредставления, вы можете скопировать/вставить свой вид и подпредставления в представление ViewController, затем внедрить его с помощью меню Editor → embed и, наконец, удалить скопированные представления..)

2) Установите следующие ограничения:

  • S к началу руководства по макету: 0
  • S к нижнему плану размещения: 0
  • S ведет к супервизору: 0
  • S тянется к superview: 0

  • V верхнее пространство для просмотра: 0

  • V нижнее пространство для просмотра: 0
  • V тянущееся пространство к superview: 0
  • V ведущее место для супервидения: 0

  • V равна ширине S

  • Последний нижний V подвид для superview: 20

3) Создайте выход из последних ограничений для вашего контроллера представления

4) Используйте следующий код:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpaceToContentView;

// ...

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    // ...

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

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

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Handle keyboard

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    self.bottomSpaceToContentView.constant = kBottomMargin + kbSize.height;
    [self.view layoutIfNeeded];
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    self.bottomSpaceToContentView.constant = kBottomMargin;
    [self.view layoutIfNeeded];
}

И тадааааа, это работает!

+5
источник

Очень просто поместить следующий код в свой класс и настроить, если вам нужно.

-(void)textFieldDidBeginEditing:(UITextField *)textField {
     //Show Keyboard
     self.view.frame = CGRectMake(self.view.frame.origin.x,
                              self.view.frame.origin.y-50,
                              self.view.frame.size.width,
                              self.view.frame.size.height);   
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
     // Hide keyboard
     self.view.frame = CGRectMake(self.view.frame.origin.x,
                              self.view.frame.origin.y+50,
                              self.view.frame.size.width,
                              self.view.frame.size.height); 
}
+5
источник

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

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

Примечание. Вам нужно изменить значение cPoint.y - 100 в соответствии с вашим представлением.

+4
источник

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

#import "UIView+avoidKeyboard.h"
#import "AppDelegate.h"

@implementation UIView (avoidKeyboard)

- (void) becomeFirstResponder {

if(self.isFirstResponder)
    return;

[super becomeFirstResponder];

if ([self isKindOfClass:[UISearchBar class]] ||
    [self isKindOfClass:[UITextField class]] ||
    [self isKindOfClass:[UITextView class]])
{
    AppDelegate *appDelegate    = [UIApplication sharedApplication].delegate;

    CGRect screenBounds         = appDelegate.window.frame;

    CGFloat keyboardHeight;
    CGFloat keyboardY;
    CGFloat viewsLowestY;
    CGPoint origin              = [self.superview convertPoint:self.frame.origin toView:appDelegate.window]; //get this views origin in terms of the main screens bounds

    if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ //the window.frame doesnt take its orientation into account so if its sideways we must use the x value of the origin instead of the y
        keyboardHeight          = 216;
        keyboardY               = screenBounds.size.height  - keyboardHeight; //find the keyboards y coord relative to how much the main window has moved up
        viewsLowestY            = origin.y + self.frame.size.height; //find the lowest point of this view
    }
    else {
        keyboardHeight          = 162;
        keyboardY               = screenBounds.size.width  - keyboardHeight;
        viewsLowestY            = origin.x + self.frame.size.height;
    }

    CGFloat difference          = viewsLowestY - keyboardY + 20; //find if this view overlaps with the keyboard with some padding

    if (difference > 0){ //move screen up if there is an overlap

        [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{

            CGRect frame = appDelegate.window.frame;

            if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){
                frame.origin.y -= difference;
            }
            else {
                frame.origin.x -= difference;
            }
            appDelegate.window.frame = frame;
        }
        completion:nil];
    }
}
}

//look at appDelegate to see when the keyboard is hidden

@end

В приложении appDelegate добавьте эту функцию

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHides:) name:UIKeyboardWillHideNotification object:nil]; //add in didFinishLaunchingWithOptions

...

- (void)keyboardHides:(NSNotification *)notification
{
    [UIView animateWithDuration:0.3 animations:^{
        [window setFrame: CGRectMake(0, 0, window.frame.size.width, window.frame.size.height)];
    } completion:nil];
}
+4
источник

Существует много ответов, говорящих о подходе. Я использовал тот же подход, но реализация не очень хороша.

Вот базовая идея. Я внесла изменения в метод keyboardWasShown.

{
// Obtain keyboard Info
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

// Obtain ScrollView Info w.r.t. top View
CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil];

// Depending upon your screen Ui, Scroll View bottom edge might be at some offset from screen bottom
// Calculate the exact offset
int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.origin.y + scrollViewRect.size.height);
int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset;


// We may also need to consider the Insets if already present with ScrollView. Let keep it simple for now
// But we should store these, so that we can restore the Insets when Keyboard is gone
// origInsets = self.scrollView.contentInset;

// Set the new Insets for ScrollView
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

// Visible frame (not overlapped by Keyboard)
CGRect visibleFrame = self.view.frame;
visibleFrame.size.height -= keyboardRect.size.height;

// Get the Rect for Textfield w.r.t self.view
CGRect activeFieldFrame = self.activeField.frame;
activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView];

// Check if the TextField is Visible or not
if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) {
    // Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View
    [self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}

}

И добавьте этот метод для инициализации activeField

- (IBAction)textFieldDidBeginEditing:(UITextField *)sender
{
self.activeField = sender;
}
+4
источник

https://github.com/michaeltyson/TPKeyboardAvoiding  загрузите этот файл и добавьте собственный класс, как это показано в вашем представлении в таблице, он будет управлять всем, что вам не нужно делать. у него есть много вариантов, которые вы можете проверить и для других, это все, что вам нужно, чтобы избежать клавиатуры

+4
источник

Это смещение, независимо от устройства. Получает перекрывающуюся высоту между клавиатурой и текстовым полем:

func keyboardShown(notification: NSNotification) {
    let info  = notification.userInfo!
    let value: AnyObject = info[UIKeyboardFrameEndUserInfoKey]!

    let rawFrame = value.CGRectValue
    let keyboardFrame = view.convertRect(rawFrame, fromView: nil)

    let screenHeight = UIScreen.mainScreen().bounds.size.height;
    let Ylimit = screenHeight - keyboardFrame.size.height
    let textboxOriginInSuperview:CGPoint = self.view.convertPoint(CGPointZero, fromCoordinateSpace: lastTextField!)

    self.keyboardHeight = (textboxOriginInSuperview.y+self.lastTextField!.frame.size.height) - Ylimit

    if(self.keyboardHeight>0){
        self.animateViewMoving(true, moveValue: keyboardHeight!)
    }else{
        keyboardHeight=0
    }
}

keyBoardHeight - это смещение.

+4
источник

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

  • Добавьте TextField и, независимо от того, что вы хотите, чтобы он плавал над клавиатурой во время редактирования, к представлению, чтобы они стали дочерними элементами представления. И тогда будет легко поддерживать внешний вид и не влиять на интерфейс пользователя.
  • Используйте отличный инструмент CGAffineTransform(TranslationX: x, TranslationY: y) , чтобы переместить созданный вид над клавиатурой.

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

+4
источник

Пожалуйста, выполните следующие действия.

1) Объявите следующую переменную в файле .h.

  {      
         CGFloat animatedDistance;
  }

2) Объявите следующие константы в файле .m.

  static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
  static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
  static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
  static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
  static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;

3) Используйте делегат UITextField для перемещения вверх/вниз по клавиатуре.

  -(void) textFieldDidBeginEditing:(UITextField *)textField
  { 
         if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
         {
               CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
               CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];

               CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
               CGFloat numerator =
    midline - viewRect.origin.y
    - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
               CGFloat denominator =
    (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
    * viewRect.size.height;
               CGFloat heightFraction = numerator / denominator;

               if (heightFraction < 0.0)
               {
                     heightFraction = 0.0;
               }
               else if (heightFraction > 1.0)
               {
                     heightFraction = 1.0;
               }

               UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
               if (orientation == UIInterfaceOrientationPortrait)
               {
                     animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
               }
               else
               {
                     animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
               }

               CGRect viewFrame = self.view.frame;
               viewFrame.origin.y -= animatedDistance;

               [UIView beginAnimations:nil context:NULL];
               [UIView setAnimationBeginsFromCurrentState:YES];
               [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

               [self.view setFrame:viewFrame];

               [UIView commitAnimations];
       }
  }

  -(void) textFieldDidEndEditing:(UITextField *)textField
  {
       if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
       {
             CGRect viewFrame = self.view.frame;
             viewFrame.origin.y += animatedDistance;

             [UIView beginAnimations:nil context:NULL];
             [UIView setAnimationBeginsFromCurrentState:YES];
             [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

             [self.view setFrame:viewFrame];

             [UIView commitAnimations];
       }
 }
+3
источник

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

MessageComposerView


(источник: thegameengine.org)

Идея этого проекта состояла в том, чтобы создать нечто, функционирующее аналогично представлению композиции iMessage AKA:

  • прилипает к верхней части клавиатуры и перемещается к нижней части экрана при отклонении клавиатуры
  • обрабатывает изменения в тексте
  • обрабатывает повороты

Чтобы изменить размер/перенастроить UIScrollView, вам нужно использовать следующий необязательный метод делегата:

- (void)messageComposerFrameDidChange:(CGRect)frame withAnimationDuration:(float)duration;

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

+3
источник

Простое решение, расширяющее UIViewController

https://github.com/damienromito/VisibleFormViewController

enter image description here

+3
источник

Я нашел, что это лучшее решение, следуйте приведенному ниже коду:

Прикрепите ниже к вашему ограничению Vertical Space - Bottom Layout Guide - TextField.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;

Второе добавьте наблюдателей для уведомлений клавиатуры.

- (void)observeKeyboard {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

Добавьте это в свой viewDidLoad

[self observeKeyboard]; 

Наконец, методы, которые обрабатывают изменения клавиатуры.

- (void)keyboardWillShow:(NSNotification *)notification {
//THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS.
kbHeight = 0;
height = 0;
self.textViewBottomConst.constant = height;
self.btnViewBottomConst.constant = height;

    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];

    CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];

    int kbHeight = finalKeyboardFrame.size.height;

    int height = kbHeight + self.textViewBottomConst.constant;

    self.textViewBottomConst.constant = height;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}

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

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    self.textViewBottomConst.constant = 10;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}
+3
источник

Я переношу все в один класс. Просто вызовите эти строки кода, когда загружен ваш диспетчер просмотра:

- (void)viewDidLoad {
    [super viewDidLoad];
    KeyboardInsetScrollView *injectView = [[KeyboardInsetScrollView alloc] init];
    [injectView injectToView:self.view withRootView:self.view];
}

Вот ссылка примера проекта:
https://github.com/caohuuloc/KeyboardInsetScrollView

+3
источник

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

Вот мой подход (слегка модифицированный способ Apple) -

// UIKeyboardDidShowNotification
- (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);
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}

// UIKeyboardWillHideNotification
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}
+3
источник

Установить прокрутку в представлении

  - (void)textFieldDidBeginEditing:(UITextField *)textField
    {
     CGPoint point;
    if(textField == txtEmail){
      // -90 is for my you can change as per your postion
      point = CGPointMake(0, textField.frame.origin.y - 90);
    }
    else if (textField == txtContact){
      point = CGPointMake(0, textField.frame.origin.y - 90);
    }
      [scrollV setContentOffset:point animated:YES];
    }
+3
источник

Для этого вы можете использовать стороннюю библиотеку (файл pod),

pod 'RDVKeyboardAvoiding'

и ссылка https://github.com/robbdimitrov/RDVKeyboardAvoiding

+3

Здесь много ответов, но это работает и намного короче большинства:

- (void)textFieldDidBeginEditing:(UITextField *)sender
{
    UIScrollView *scrollView = (UIScrollView *)self.view; // assuming this method is pasted into the UIScrollView controller
    const double dontHardcodeTheKeyboardHeight = 162;
    double textY = [sender convertPoint:CGPointMake(0, 0) toView:scrollView].y;
    if (textY - scrollView.contentOffset.y + sender.frame.size.height > self.view.frame.size.height - dontHardcodeTheKeyboardHeight)
        [scrollView setContentOffset:CGPointMake(0.0, textY - 10) animated:YES];
}
+2
источник

Просто нашел этот класс:

https://github.com/OliverLetterer/SLScrollViewKeyboardSupport

И пока это хорошо работает на iPhone, включая анимацию и правильное смещение.

Чтобы использовать его, просто добавьте в viewDidLoad:

self.support = [[SLScrollViewKeyboardSupport alloc] initWithScrollView:self.scrollView];
+2
источник
  • Если текстовое поле не полностью или частично скрыто, мы ничего не должны изменять.
  • Мы должны вычислить точную область пересечения (рамку клавиатуры и рамки текстового поля), которая скрыта, а затем мы должны изменить рамку представления.

  • Здесь я даю полный пример.

    Объявление 3 разновидности

#define PADDING 10

@interface PKViewController ()
      @property (nonatomic, assign) CGRect originalViewFrame; //original view frame
      @property (nonatomic, strong) UITextField *activeTextField; // current text field
      @property (nonatomic, assign) CGRect keyBoardRect; // covered area by keaboard
     @end

Сохранить исходный фрейм

- (void)viewDidLoad {
    [super viewDidLoad];
    _originalViewFrame = self.view.frame;
}

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

- (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];
}

Удалить наблюдателя

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Сохраните область, закрытую клавиатурой, когда она появится, и установите ее в CGRectZero, когда она исчезнет

- (void)keyboardWasShown:(NSNotification *)notification{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    _keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height);
    [self moveTextFieldUP];

}
- (void) keyboardWillHide:(NSNotification *)notification{
    _keyBoardRect = CGRectZero;
    [self setDefaultFrame];
}

Сохранить активное текстовое поле

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    _activeTextField = textField;
//When keyboard is already present but the textfield is hidden. Case:When return key of  keyboard makes the next textfield as first responder
    if (!CGRectIsEmpty(_keyBoardRect)) { 
        [self moveTextFieldUP];
    }
    return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
}

Теперь мы должны изменить кадр вида

- (void)moveTextFieldUP{
    CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.origin.y, _activeTextField.frame.size.width, _activeTextField.frame.origin.y+_activeTextField.frame.size.height);
    if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) {
        CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect);
        CGFloat newY = _originalViewFrame.origin.y - intersectRect.size.height;
        CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height;
        CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING);
        [UIView animateWithDuration:0.3 animations:^{
            [self.view setFrame:newFrame];
        }];

        NSLog(@"Intersect");
    }
}
- (void)setDefaultFrame {
    [UIView animateWithDuration:0.3 animations:^{
        [self.view setFrame:_originalViewFrame];
    }];
}
+2
источник
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField {

  [self slideUp];
   return YES;
}

-(BOOL) textFieldShouldEndEditing:(UITextField *)textField {

    [self slideDown];
   return YES;
}

#pragma mark - Slide Up and Down animation

- (void) slideUp {
    [UIView beginAnimations:nil context:nil];
    layoutView.frame = CGRectMake(0.0, -70.0, layoutView.frame.size.width, layoutView.frame.size.height);

    [UIView commitAnimations];
}


- (void) slideDown {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelay: 0.01]; 
    layoutView.frame = CGRectMake(0.0, 0.0, layoutView.frame.size.width, layoutView.frame.size.height);
    [UIView commitAnimations];
}
+2
источник

Простое решение и с последней анимацией api. Изменив значение origin.y на 215, вы можете настроить его в зависимости от того, какое значение вам подходит.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (self.view.frame.origin.y >= 0) {

        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-215, self.view.frame.size.width, self.view.frame.size.height);
       }];
   }
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    if (self.view.frame.origin.y < 0) {
        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+215, self.view.frame.size.width, self.view.frame.size.height);
        }];

    }
}
+2
источник

Пожалуйста, добавьте эти строки в метод делегата текстового поля, чтобы прокрутить вверх в iPad.

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

    CGPoint pt;
    CGRect rc = [textField bounds];
    rc = [textField convertRect:rc toView:scrlView];
    pt = rc.origin;
    pt.x = 0;
    pt.y -= 100;

    [scrlView setContentOffset:pt animated:YES];

    scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.origin.y+button.frame.size.height + 8 + 370);
}
+2
источник

Это можно сделать легко и автоматически, если это текстовое поле находится в ячейке таблицы (даже если table.scrollable = NO).

  • ПРИМЕЧАНИЕ: позиция и размер таблицы должны быть разумными. например:
    • если y позиция таблицы 100 подсчитана из нижней части представления, тогда клавиатура высотой 300 будет перекрывать всю таблицу.
    • если высота таблицы = 10, а текстовое поле в ней должно быть прокручено до 100, когда клавиатура появляется, чтобы быть видимой, тогда это текстовое поле будет вне таблицы.
+2
источник

Посмотрите другие вопросы по меткам или Задайте вопрос