Вопрос по keyboard, uitextfield, iphone – Крышки клавиатуры iPhone UITextField

119

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

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

Возможный дубликатHow to make a UITextField move up when keyboard is present Ratul Sharker

Ваш Ответ

20   ответов
0

если вы используете cocos2d в портретном режиме, измените эту строку:

self.view.frame = CGRectOffset(self.view.frame, 0, movement);

к этому:

[CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0);

Если вы используете cocos2d в ландшафтном режиме, внесите вышеуказанные изменения и переключитеup значения вtextFieldDidBeginEditing: а такжеtextFieldDidEndEditing:

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

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

Перемещение содержимого, расположенного под клавиатурой

Adjusting your content typically involves temporarily resizing one or more views and positioning them so that the text object remains visible. The simplest way to manage text objects with the keyboard is to embed them inside a UIScrollView object (or one of its subclasses like UITableView). When the keyboard is displayed, all you have to do is reset the content area of the scroll view and scroll the desired text object into position. Thus, in response to a UIKeyboardDidShowNotification, your handler method would do the following:

Get the size of the keyboard. Adjust the bottom content inset of your scroll view by the keyboard height. Scroll the target text field into view.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(keyboardWasShown:)
            name:UIKeyboardDidShowNotification object:nil];

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

}

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

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}
@Raj, это может быть тот случай, который я могу посмотреть на IQKeyboardManager, но до сих пор никто не открывает никаких проблем в официальном репозитории gitub IQKeyboardManager, касающихся проблемы со свойством contentInset, поэтому я предполагаю, что это работает.
Идея хорошая, но "contentInset" свойство здесь не помогает, потому что contentInset просто предоставит вам эффект заполнения:stackoverflow.com/a/10049782/260665
Это официальное решение теперь включено в элемент управления, см. Здесь: -stackoverflow.com/a/17707094/1582217
290

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

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


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

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

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

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}
Очень нравится, что вы опубликовали не ссылку на код, а сам код.
Нашел это и обсуждает ту же проблемуdeveloper.apple.com/Library/ios/documentation/StringsTextFonts/…
Большой кусок кода. Не нужно было его редактировать, чтобы он работал или что-то еще. Благодаря ~
Полезно охватить весь экран, как показано ниже: const int motionDistance = textField.frame.origin.y / 2; // настроить по мере необходимости
Я должен упомянуть, что "если вы пишете приложение для iOS 4 или более поздней версии, вы должны использовать блочные методы для анимации вашего контента." Ссылка от:developer.apple.com/library/ios/#documentation/windowsviews/…
38

Скользящие поля текста

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

Приведенная выше ссылка просто сделала мой день! Так просто реализовать, до сих пор работает без нареканий!
Лучшее решение на сегодняшний день. Феноменальный механизм!
Это замечательно. Вам не нужно выбирать «расстояние перемещения»; константа для каждого текстового поля - рассчитывается для вас.
Отлично работает на iPad тоже. Я только что обновил PORTRAIT_KEYBOARD_HEIGHT = 264 и LANDSCAPE_KEYBOARD_HEIGHT = 352. Отличная ссылка. Благодарю.
Это лучшее объяснение этой темы. Другие учебники используют Table Views, Scroll Views и т. Д. Это на самом деле работает, не вдаваясь в какие-либо другие сложности, простые и понятные. Спасибо, что поделились этим источником.
0

и я обнаружил, что GTKeyboardHelper - это легкий выход.

После перетаскивания рамки в вашем проекте, включите заголовочный файл. Загрузите и откройте пример проекта, затем перетащите & quot; Keyboard Helper & quot; Объект из раздела объектов в XIB к разделу объектов в конструкторе интерфейса вашего проекта.

Перетащите все свои представления, чтобы они были дочерними элементами & quot; Keyboard Helper & quot ;.

7

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

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

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

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

(void)keyboardWasShown:(NSNotification*)aNotification 
(void)keyboardWillBeHidden:(NSNotification*)aNotification 
Ссылка не работает. Пожалуйста, подумайте о включении независимого решения в будущем!
1

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

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect frame=self.view.frame;
    frame.origin=CGPointMake(x...//set point here
    self.view.frame=frame;
}
Нет, это не так. Если пользователь коснется первого текстового поля, оно окажется над видимой областью.
0

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

0

https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example Я надеюсь, что это решение помогло. Все они написаны на Swift 3.

//
//  ViewController.swift
//  Shift Keyboard Example
//
//  Created by Zulwiyoza Putra on 11/23/16.
//  Copyright © 2016 Zulwiyoza Putra. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    
    
    //connecting textfield from storyboard
    @IBOutlet weak var textField: UITextField!
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        subscribeToKeyboardNotifications()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        self.textField.delegate = self
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        unsubscribeFromKeyboardNotifications()
    }
    
    //Hide keyboard after finished editing
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    //Setup view before keyboard appeared
    func keyboardWillAppear(_ notification:Notification) {
        view.frame.origin.y = 0 - getKeyboardHeight(notification)
    }
    
    //Setup view before keyboard disappeared
    func keyboardWillDisappear(_ notification: Notification) {
        view.frame.origin.y = 0
    }
    
    //Getting keyboard height
    func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
        return keyboardSize.cgRectValue.height
    }
    
    //Subscribing to notifications to execute functions
    func subscribeToKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: .UIKeyboardWillHide, object: nil)
    }
    
    //Unsubscribing from notifications
    func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
    }
    
}

0

если хотите. Дело в том, что вы хотите установить центр вашего UIView на текстовое поле, которое вы редактируете.

До этого вы должны сохранитьINITIAL_CENTER, какCGPoint, из self.view.center и вашегоINITIAL_VIEW какCGRect из self.view.frame в свойстве const.

Вы можете создать такой метод:

- (void) centerOn: (CGRect) fieldFrame {

    // Set up the center by taking the original view center
    CGPoint center = CGPointMake(INITIAL_CENTER.x,
                             INITIAL_CENTER.y - ((fieldFrame.origin.y + fieldFrame.size.height/2) - INITIAL_CENTER.y));


    [UIView beginAnimations:@"centerViewOnField" context:nil];
    [UIView setAnimationDuration:0.50];

    if (CGRectEqualToRect(fieldFrame,INITIAL_VIEW)) {
        self.view.frame = INITIAL_VIEW;
        [self.view setCenter:INITIAL_CENTER];
    } else {
        [self.view setCenter:center];
    }


    [UIView commitAnimations];
}

Тогда на вашемUITextFieldDelegate, ты должен позвонитьcenterOn:(CGRect) в следующих методах:

textFieldDidBeginEditing:(UITextField*) с, в качестве параметра, рамкой текстового поля, на котором вы хотите сосредоточиться.

И вы должны вызвать его в вашем обработчике событий, где вы закрываете клавиатуру,

textFieldDidEndEditing:(UITextField*) может быть одним из способов сделать это, поместив INITIAL_VIEW в качестве параметраcenterOn:(CGRect).

0

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

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

затем:

- (void)keyboardWasShown:(NSNotification*)notification
{
    // Scroll the text field into view so it's not under the keyboard.
    CGRect rect = [self.tableView convertRect:inputView.bounds fromView:inputView];
    [self.tableView scrollRectToVisible:rect animated:YES];
}
работает только для таблицы
5

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

TPKeyboardAvoiding

@NANNAV - Пожалуйста, оставляйте комментарии, когда вы предлагаете изменить ответ.
28

IQKeyboardManager сделай это для тебя сNO LINE OF CODE, только нужно перетащить связанный исходный файл в проект.IQKeyboardManager также поддержкаDevice Orientation, Automatic UIToolbar Management, keyboardDistanceFromTextField и гораздо больше, чем вы думаете.

enter image description here

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

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

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

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

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

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

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

Step7:- ВосстановленаtopMostViewController.view.frame вниз по нарушенному расстоянию.

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

Вот и все

Не работает для iPad.
Хорошая работа, работает отлично.
Принятый ответ не работал для меня. Но этот делает.
@ZaEeMZaFaR IQKeyboardManager также оптимизирован для iPad. Не могли бы вы открыть выпуск библиотеки github repo и загрузить демонстрационный проект, демонстрирующий проблему с iPad?
Спасибо за ответ. Я сделаю это, если проблема не исчезнет, прежде чем вы прокомментируете, я подумал, что IQKeyboardManager не для универсального устройства.
0

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

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

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

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

    [UIView animateWithDuration:movementDuration animations:^{
        self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    }];
}

Не забудьте установитьself какUITextFieldDelegate и как фактический textFielddelegate.

(Спасибо Ammagrammer, это просто более короткий ответ с использованием блоков для анимации)

2

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

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

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

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

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.MyTextField.delegate = self;

}

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

      CGPoint MyPoint = self.MyTextField.center;

      [UIView animateWithDuration:0.3
                    animations:^{

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

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

     CGPoint MyPoint = self.MyTextField.center;

     [UIView animateWithDuration:0.3
                 animations:^{

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

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

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

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

5

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

var keyboardHeight:CGFloat = 0

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

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

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

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

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

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

func keyboardWillChange(notification:NSNotification) {
    let keyboardRect:CGRect = ((notification.userInfo![UIKeyboardFrameEndUserInfoKey])?.CGRectValue)!
    keyboardHeight = keyboardRect.height
    animateTextField(true)
}
0
7

LoginViewController.h

@interface LoginViewController : UIViewController <UITextFieldDelegate> {

}

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

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

LoginViewController.m

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

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


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

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

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

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


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

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}
//This is called when the app goes into the background.
//We must reset the responder because animations will not be saved
- (void)appEnteredBackground{
    [self.emailTextField resignFirstResponder];
    [self.passwordTextField resignFirstResponder];
}
+1 за упоминаниеUIApplicationDidEnterBackgroundNotificationв противном случае он будет перемещаться вниз, если нажать кнопку «Домой» и снова войти в приложение, что приведет к тому, что оно будет уродливым и глючным.
0

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

GTKeyboardHelper

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