Как я могу заставить 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 ответов

Очень легкое решение может использовать KeyboardAnimator.

Проект

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

Соответствующее использование:: Он имеет конкретную реализацию для UITextField и UITextView

Ограничение:: В полной версии objective-c скоро появится скоростная версия.

+2
источник

Это будет работать Perfectly. Прокрутка просмотра atmatically настроить по положению textfield.I уверен, что вы будете чувствовать себя хорошо

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.25;
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;
@interface LoginVC ()
{
  CGFloat animatedDistance;
   CGRect viewFrameKey;
}

 //In ViewDidLoad
   viewFrameKey=self.view.frame;



- (void)textFieldDidBeginEditing:(UITextField *)textField
{
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 ||
    orientation == UIInterfaceOrientationPortraitUpsideDown)
{
    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
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrameKey];
[UIView commitAnimations];
}
+2
источник
другие ответы

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


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

Я хотел бы продлить ответ @sumanthkodi.

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

Я отредактировал код следующим образом (и портирован на Swift 2.0) и надеюсь, что он поможет некоторым людям:


1) Ссылка на вертикальное ограничение вида, которое вы хотели бы переместить вверх:

@IBOutlet var viewConstraint: NSLayoutConstraint!

Убедитесь, что вы ссылаетесь на этот var в раскадровке с ограничением.

2) Добавить делегата и реализовать слушателей. Это та же самая реализация, что и раньше:

class YourViewController: UIViewController, UITextFieldDelegate {

    ...

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

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

    ...

}

3) Добавьте свой метод анимации animateTextField в YourViewController. Установите необходимое временное ограничение.

func animateTextField(textfield: UITextField, up: Bool) {

    let originalConstraint = 50
    let temporaryConstraint = 0
    let movementDuration = 0.3

    let constraint = CGFloat(up ? temporaryConstraint : originalConstraint)

    containerViewConstraint.constant = constraint
    UIView.animateWithDuration(movementDuration) {
        self.view.layoutIfNeeded()
    }

}
+2
источник

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

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

- (void)keyboardWillShow:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]];
}

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

- (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info {
    CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat height = keyboardFrame.size.height;
    self.constraintToAdjust.constant = height;        UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
    UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState;
    if (animationCurve == UIViewAnimationCurveEaseIn) {
        animationOptions |= UIViewAnimationOptionCurveEaseIn;
    }
    else if (animationCurve == UIViewAnimationCurveEaseInOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseInOut;
    }
    else if (animationCurve == UIViewAnimationCurveEaseOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseOut;
    }
    else if (animationCurve == UIViewAnimationCurveLinear) {
        animationOptions |= UIViewAnimationOptionCurveLinear;
    }
    [UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{
        [self.view layoutIfNeeded];
    }                completion:nil];
}
+2
источник

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

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

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

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}
+2
источник
  • Загрузить TPKeyBoardAvoiding По этой ссылке: https://github.com/michaeltyson/TPKeyboardAvoiding.
  • Разверните папку zipped и найдите папку TPKeyboardAvoiding.
  • Выделите все файлы .h и .m и поместите их в свой проект. Убедитесь, что элементы копии, если необходимо, отмечены галочкой.
  • Перетащите UIScrollView на StoryBoard и свяжите его с TPKeyboardAvoidingScrollView.
  • Теперь вы можете добавить элементы пользовательского интерфейса в верхней части прокрутки. Обратите внимание, что этот класс обнаруживает элементы интерфейса, даже после перетаскивания scrollView.

На вашем ViewController:

@IBOutlet weak var usernameTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var loginScrollView: UIScrollView!


override func viewWillAppear(animated: Bool) {
        loginScrollView.scrollEnabled =  false
    }

Добавить делегатов TextField.

//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool
{
    if (usernameTextfield.resignFirstResponder())
    {
        passwordTextfield.becomeFirstResponder()
    }
    textField.resignFirstResponder();
    loginScrollView!.setContentOffset(CGPoint.zero, animated: true);
    loginScrollView.scrollEnabled =  false
    return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
    loginScrollView.scrollEnabled =  true

    if (textField.tag  == 1 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.4);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);

    }
    else if (textField.tag  == 2 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.0);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);
    }
}
func textFieldDidEndEditing(textField: UITextField)
{
    loginScrollView!.setContentOffset(CGPointZero,animated: true);
}
+2
источник

Этот фрагмент кода рассчитает, сколько нужно двигаться вверх, исходя из высоты клавиатуры и глубины текстового поля. Не забудьте добавить делегат и наследовать UITextFieldDelegate в своем заголовке.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [_tbxUsername resignFirstResponder];
    [_tbxPassword resignFirstResponder];
}

- (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
{
    int animatedDistance;
    int moveUpValue = textField.frame.origin.y+ textField.frame.size.height;
    UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {

        animatedDistance = 236-(460-moveUpValue-5);
    }
    else
    {
        animatedDistance = 182-(320-moveUpValue-5);
    }

    if(animatedDistance>0)
    {
        const int movementDistance = animatedDistance;
        const float movementDuration = 0.3f;
        int movement = (up ? -movementDistance : movementDistance);
        [UIView beginAnimations: nil context: nil];
        [UIView setAnimationBeginsFromCurrentState: YES];
        [UIView setAnimationDuration: movementDuration];
        self.view.frame = CGRectOffset(self.view.frame, 0, movement);
        [UIView commitAnimations];
    }
}

Делегировать для добавления в ViewDidLoad

_tbxUsername.delegate = self;
_tbxPassword.delegate = self;
+2
источник

Попробуйте библиотеку IQKeyboard.

Это автоматически переместит текстовое поле вверх.

+2
источник

Swift 3.0 версия кода управления клавиатурой Apple: FloatingTF, используемый в приведенном ниже коде, является текстовым полем, основанным на материалах, в iOS.

import UIKit
class SignupViewController: UIViewController, UITextFieldDelegate {

    //MARK: - IBOutlet:
@IBOutlet weak var emailTF: FloatingTF!
@IBOutlet weak var passwordTF: FloatingTF!
@IBOutlet weak var dobTF: FloatingTF!

@IBOutlet weak var scrollView: UIScrollView!

//MARK: - Variable:
var activeTextField: UITextField!

//MARK: - ViewController Lifecycle:
override func viewDidLoad() {
    super.viewDidLoad()        
    emailTF.delegate = self
    passwordTF.delegate = self
    dobTF.delegate = self 
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    registerKeyboardNotifications()
}
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

   deRegisterKeyboardNotifications()
}

//MARK: - Keyboard notification observer Methods
fileprivate func registerKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func deRegisterKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {

    let info: NSDictionary = notification.userInfo! as NSDictionary
    let value: NSValue = info.value(forKey: UIKeyboardFrameBeginUserInfoKey) as! NSValue
    let keyboardSize: CGSize = value.cgRectValue.size
    let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0)
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets

    // If active text field is hidden by keyboard, scroll it so it visible
    // Your app might not need or want this behavior.
    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
    if (!aRect.contains(activeTextFieldOrigin!)) {
        scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
    }    }

func keyboardWillHide(notification: NSNotification) {
    let contentInsets: UIEdgeInsets = .zero
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets
}

//MARK: - UITextField Delegate Methods
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if textField == emailTF {
        passwordTF.becomeFirstResponder()
    }
    else if textField == passwordTF {
        dobTF.becomeFirstResponder()
    }
    else {
        self.view.endEditing(true)
    }
    return true
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    activeTextField = textField
    scrollView.isScrollEnabled = true
}

func textFieldDidEndEditing(_ textField: UITextField) {
    activeTextField = nil
    scrollView.isScrollEnabled = false
}
}
+2
источник

Простое решение для Scrollview с TextFields ниже, не нужно никаких ограничений или активного текстового поля и т.д.

 override func viewWillAppear(_ animated: Bool){
        super.viewWillAppear(animated)
        registerForKeyboardNotifications();


    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        deregisterFromKeyboardNotifications();
    }
    //MARK:- KEYBOARD DELEGATE METHODS
        func registerForKeyboardNotifications(){
            //Adding notifies on keyboard appearing
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func deregisterFromKeyboardNotifications(){
            //Removing notifies on keyboard appearing
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func keyboardWasShown(notification: NSNotification){

            var info = notification.userInfo!
            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = (keyboardSize?.height)!
            scrRegister.contentInset = contentInset


        }
        func keyboardWillBeHidden(notification: NSNotification)
        {
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = 0
            scrRegister.contentInset = contentInset

        }
+2
источник

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

Спасибо

+1
источник

просто: -

В TextFieldDidBeginEditing: -

self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-150, self.view.frame.size.width, self.view.frame.size.height);

В TextFieldShouldEndEditing: -

self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+150, self.view.frame.size.width, self.view.frame.size.height);
+1
источник

Я немного опаздываю. Вы должны добавить scrollView на свой viewController.

Вы должны реализовать метод ниже 2.

Метод делегата TextField.

    - (void)textFieldDidBeginEditing:(UIView *)textField {
    [self scrollViewForTextField:reEnterPINTextField];
}

Затем вызовите метод meton в методе делегата.

 - (void)scrollViewForTextField:(UIView *)textField {
    NSInteger keyboardHeight = KEYBOARD_HEIGHT;

    if ([textField UITextField.class]) {
        keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
    } 

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
    aRect.size.height -= keyboardHeight;
    CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
    CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);

    if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
        CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
        [contentSlidingView setContentOffset:scrollPoint animated:YES];
    }
}
+1
источник

Используя IQKeyboardManager, UITextField и UITextView автоматически прокручиваются при появлении клавиатуры. Ссылка на Git: https://github.com/hackiftekhar/IQKeyboardManager.

pod: pod 'IQKeyboardManager' # iOS8 и более поздние версии

модуль 'IQKeyboardManager', '3.3.7' # iOS7

+1
источник

см. UICatalogView примеры iphone live и загруженные

0
источник

Я не видел эту возможность здесь, поэтому я добавляю ее, так как я пробовал методы в ответах, но через несколько часов обнаружил, что в XCode 5 в iOS6/7 есть намного более простой способ: Используйте NSLayoutConstraints.

Смотрите: Ограничение автоопределения - Клавиатура

Вот мой код:

.m file:

// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
    NSLog(@"keyboardWillBeShown:");
    [self.PhoneNumberLabelOutlet setHidden:TRUE];
    CGFloat heightOfLabel = self.PhoneNumberLabelOutlet.frame.size.height;
    for( NSLayoutConstraint* thisConstraint in self.topElementsVerticalDistanceFromTopLayoutConstraint ) {
        thisConstraint.constant -= heightOfLabel;
    }

    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGFloat oldConstant = [self.SignInYConstraint constant];
    self.SignInYConstraint.constant = oldConstant + kbSize.height;
    [self.view setNeedsUpdateConstraints];

    NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        [self.view layoutIfNeeded];
    }];

}

.h файл:

#import <UIKit/UIKit.h>

@interface SignInViewController : UIViewController {

    UITextField* _activeField;
}




- (void)signInCallback:(NSObject*)object;


@property (weak, nonatomic) IBOutlet UILabel *PhoneNumberLabelOutlet;

@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *ActivityIndicatorOutlet;

@property (weak, nonatomic) IBOutlet UITextField *UserIDTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UITextField *PasswordTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UIButton *SignInButton;

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

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *topElementsVerticalDistanceFromTopLayoutConstraint;

@end
0
источник

Я нашел @DK_ для решения, которое начал использовать. Однако есть предположение, что scrollView охватывает весь вид. Это было не так для меня. Я только хотел scrollView в случае, если клавиатура закрыла нижнее текстовое поле на моем экране входа в систему. Поэтому мой контент был такого же размера, как и мой вид прокрутки, который был меньше основного.

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

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    // A lot of the inspiration for this code came from http://stackoverflow.com/a/4837510/594602
    CGFloat height = 0;
    NSDictionary* info = [aNotification userInfo];

    CGRect kbFrameRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect kbBoundsRect = [self.view convertRect:kbFrameRect fromView:nil]; // Convert frame from window to view coordinates.

    CGRect scrollRect = scrollView.frame;
    CGRect intersect = CGRectIntersection(kbBoundsRect, scrollRect);

    if (!CGRectIsNull(intersect))
    {
        height = intersect.size.height;
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // Figure out what the view rectangle is for the scrollView
    CGPoint contentOffset = scrollView.contentOffset;
    CGRect visibleRect = CGRectOffset(scrollRect, contentOffset.x, contentOffset.y);    // I'm not 100% sure if this is needed/right. My scrollView was always at the top in testing.
    visibleRect.size.height -= height;
    CGRect activeRect = activeField.frame;

    if (!CGRectContainsRect(visibleRect, activeRect))
    {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

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

Я думаю, что ключевая часть заключалась в том, что представление контента имело заданную ширину и высоту. Это позволило просматривать прокрутку, чтобы точно знать, сколько контента ей пришлось иметь. Это немного отстает от обычных макетов. Обычно взгляды пытаются взять как можно больше места. С содержимым вида прокрутки вы пытаетесь получить представление как можно больше. Представление контента позволяет вам остановиться на этом. Поэтому я дал мне высоту 248 и использовал стандартную ширину экрана 320 в качестве моей ширины.

Макеты, которые в конечном итоге сработали для меня, были следующими:

  • Scroll View to super view: В основном я дал ограничения для верхнего, левого и правого.
    • Horizontal Space - View - Scroll View (0)
    • Vertical Space - View - Scroll View (0)
    • Horizontal Space - Scroll View - View (0)
  • Прокрутка Высота просмотра: я устанавливаю вид прокрутки с постоянной высотой. Я не знаю, действительно ли это было необходимо, но оно получило границы прокрутки.
    • Height - (248) - Scroll View
  • Вид содержимого в виде прокрутки: я дал константы со всех сторон, сверху, слева, внизу и справа.
    • Vertical Space - View - Scroll View (0)
    • Vertical Space - Scroll View - View (0)
    • Horizontal Space - View - Scroll View (0)
    • Horizontal Space - Scroll View - View (0)
  • Размеры представления содержимого.
    • Height - (248) - View
    • Width - (320) - View
0
источник

in (BOOL) textFieldShouldBeginEditing: (UITextField *) textField

if (textField.frame.origin.y > self.view.frame.size.height - 216)
    {
        if (screenHeight>500)
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 100);
        else
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 216);
        CGPoint scrollPoint = CGPointMake(0.0,(textField.frame.origin.y - (self.view.frame.size.height - 216 - textField.frame.size.height - 20)));
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
    [scrollView setScrollEnabled:YES];

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

scrollView.contentSize = CGSizeMake(0.0, 640);
CGPoint scrollPoint = CGPointMake(0.0,0.0);
[scrollView setContentOffset:scrollPoint animated:YES]; 
0
источник

Я использую Swift и auto layout (но не могу прокомментировать предыдущий ответ Swift); здесь, как я делаю это без прокрутки:

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

Это можно вызвать с помощью любого из обычных методов textFieldDidBeginEditing или keyboardWillShow.

func setFormHeight(top: CGFloat)
{
    let height = UIScreen.mainScreen().bounds.size.height

    // restore text input fields for iPhone 4/4s
    if (height < 568) {
        UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: {
            self.topSpaceForFormConstraint.constant = top
            self.view.layoutIfNeeded()
            }, completion: nil)
    }

}
0
источник

Это сработало для меня:

func setupKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWasShown:"), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillBeHidden:"), name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height -= kbSize.height

    self.view.frame = rect
    UIView.commitAnimations()
}

func keyboardWillBeHidden(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height += kbSize.height
    self.view.frame = rect
    UIView.commitAnimations()
}
0
источник

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

Я предпочитаю использовать этот контроль Github.

IQKeyboard

В котором Нам не нужно ничего делать. - просто перетащите элемент управления перетаскиванием в свой проект и создайте. - Он сделает все для вашего приложения.

Спасибо

Возможно, это будет полезно.

0
источник

У меня возникла проблема с переходом к основному виду по умолчанию при изменении текстового поля или редактировании его содержимого (например, текстовое поле телефона и добавление знака "-", а просмотр - закрытие текстовых полей) i finnaly преодолевает это, используя автоматическую компоновку и изменяя ограничения постоянными, а не размер кадра или позицию в функции делегирования уведомлений, например:

P.S. Я не использую scrollview только для простого перемещения, но он должен работать с аналогичным

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    if !keyboardIsShown{
        self.infoViewTopConstraint.constant -= keyboardSize.height
        self.infoViewBottomConstraint.constant += keyboardSize.height
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
        keyboardIsShown = true
    }
}

func keyboardWillHide(notification: NSNotification) {
if keyboardIsShown {
    self.infoViewTopConstraint.constant += keyboardSize.height
    self.infoViewBottomConstraint.constant -= keyboardSize.height
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
    keyboardIsShown = false
}
0
источник

Для Swift Developer, использующего Swift 3, здесь находится repo https://github.com/jamesrochabrun/KeyboardWillShow

import UIKit

class ViewController: UIViewController {

    //1 Create a view that will hold your TEXTFIELD
    let textField: UITextField = {
        let tf = UITextField()
        tf.translatesAutoresizingMaskIntoConstraints = false
        tf.layer.borderColor = UIColor.darkGray.cgColor
        tf.layer.borderWidth = 3.0
        return tf
    }()
    //2 global variable that will hold the bottom constraint on changes
    var textfieldBottomAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        //3 add the view to your controller
        view.addSubview(textField)
        textField.heightAnchor.constraint(equalToConstant: 80).isActive = true
        textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
        textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        textfieldBottomAnchor?.isActive = true

        setUpKeyBoardObservers()
    }
    //4 Use NSnotificationCenter to monitor the keyboard updates
    func setUpKeyBoardObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    //5 toggle the bottom layout global variable based on the keyboard height
    func handleKeyboardWillShow(notification: NSNotification) {

        let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect
        if let keyboardFrame = keyboardFrame {
            textfieldBottomAnchor?.constant = -keyboardFrame.height
        }
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }

    func handleKeyboardWillHide(notification: NSNotification) {

        textfieldBottomAnchor?.constant = 0
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
    //6 remove the observers
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NotificationCenter.default.removeObserver(self)
    }
}
0
источник

Вы можете использовать этот простой репозиторий Git: https://github.com/hackiftekhar/IQKeyboardManager

Это библиотека, которая автоматически управляет всеми перемещениями полей.

Согласно их readme, интеграция очень проста:

, без необходимости вводить код, и никакой дополнительной настройки не требуется. Чтобы использовать IQKeyboardManager, вам просто нужно добавить исходные файлы в свой проект

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

0
источник

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

Но для меня идеей решения должен быть UITableViewController со статическими ячейками.

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

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

0
источник

Мы можем пользовательский код для Swift 4.1

    let keyBoardSize = 80.0

    func keyboardWillShow() {

    if view.frame.origin.y >= 0 {
    viewMovedUp = true
     }
     else if view.frame.origin.y < 0 {
    viewMovedUp = false
   }
  }

func keyboardWillHide() {
 if view.frame.origin.y >= 0 {
    viewMovedUp = true
 }
 else if view.frame.origin.y < 0 {
    viewMovedUp = false
 }

}

func textFieldDidBeginEditing(_ textField: UITextField) {
   if sender.isEqual(mailTf) {
    //move the main view, so that the keyboard does not hide it.
    if view.frame.origin.y >= 0 {
        viewMovedUp = true
    }
  }
}

func setViewMovedUp(_ movedUp: Bool) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
    // if you want to slide up the view
let rect: CGRect = view.frame
if movedUp {

    rect.origin.y -= keyBoardSize
    rect.size.height += keyBoardSize
}
else {
    // revert back to the normal state.
    rect.origin.y += keyBoardSize
    rect.size.height -= keyBoardSize
 }
 view.frame = rect
 UIView.commitAnimations()
}

func viewWillAppear(_ animated: Bool)  {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}

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

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
0
источник

Добавьте мои 5 центов :)

Я всегда предпочитаю использовать tableView для inputTextField или scrollView. В сочетании с уведомлениями вы можете легко управлять таким поведением. (Обратите внимание, если вы используете статические ячейки в tableView, такое поведение будет работать автоматически).

// MARK: - Notifications
fileprivate func registerNotificaitions() {
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

fileprivate func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self)
}

@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        view.layoutIfNeeded()
        UIView.animate(withDuration: 0.3, animations: {
            let heightInset = keyboardHeight - self.addDeviceButton.frame.height
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

@objc fileprivate func keyboardWillDisappear() {
    view.layoutIfNeeded()
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset = UIEdgeInsets.zero
        self.view.layoutIfNeeded()
    }, completion: nil)
}
0
источник

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

override var inputAccessoryView: UIView? {
    return <yourTextField>
}
0
источник

Пожалуйста, используйте IQKeyboardManager, используйте следующую ссылку: https://github.com/hackiftekhar/IQKeyboardManager

0
источник

Swift 5

в viewDidLoad или viewDidAppear добавьте метод addKeyboardObservers.

fileprivate func addKeyboardObservers(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

fileprivate func removeKeyboardObservers(){
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}


@objc fileprivate func keyboardWillHide(_ notification: Notification){
    if (window == nil) {return}
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = .zero
}


@objc fileprivate func keyboardWillShow(_ notification: Notification){
    if (window == nil) {return}
    if UIApplication.shared.applicationState != .active { return }

    // keyboard height
    guard let height = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height else {return}
    // keyboard present animation duration
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = height
}

не забудьте удалить наблюдателей на deinit или исчезнуть

    self.removeKeyboardObservers()
0
источник

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