ios iPhone 键盘覆盖 UITextField

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1247113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:15:54  来源:igfitidea点击:

iPhone Keyboard Covers UITextField

iosiphonekeyboarduitextfield

提问by Cruinh

I have an app where, in Interface Builder, I set up a UIViewthat has a text field near the bottom of the view. When I run the app and try to enter text into that field, the keyboard slides up overtop of the field so I can't see what I'm typing until I hide the keyboard again.

我有一个应用程序,在Interface Builder 中,我设置了一个UIView在视图底部附近有一个文本字段的应用程序。当我运行应用程序并尝试在该字段中输入文本时,键盘会滑到该字段的上方,因此在我再次隐藏键盘之前我看不到我正在输入的内容。

Has anyone else run into this problem and found a good way to solve it without either making the parent view scrollable or moving the text field farther up the screen?

有没有其他人遇到过这个问题并找到了解决它的好方法,而无需使父视图可滚动或将文本字段移到屏幕更远的位置?

回答by Amagrammer

The usual solution is to slide the field (and everything above it) up with an animation, and then back down when you are done. You may need to put the text field and some of the other items into another view and slide the view as a unit. (I call these things "plates" as in "tectonic plates", but that's just me). But here is the general idea if you don't need to get fancy.

通常的解决方案是使用动画向上滑动字段(及其上方的所有内容),然后在完成后返回。您可能需要将文本字段和其他一些项目放入另一个视图中,并将视图作为一个单元滑动。(我称这些东西为“板块”,就像“构造板块”一样,但这只是我自己)。但如果您不需要花哨的话,这里是一般的想法。

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

回答by cidered

This worked wonders for me sliding uitextfields

这对我滑动 uitextfields 有奇效

In particular it has the benefit of calculating the slide animation distance depending on the position of the text field.

特别是它具有根据文本字段的位置计算幻灯片动画距离的好处。

回答by Mohd Iftekhar Qurashi

IQKeyboardManagerdo this for you with NO LINE OF CODE, only need to drag and drop related source file to project. IQKeyboardManageralso support Device Orientation, Automatic UIToolbar Management, keyboardDistanceFromTextFieldand much more than you think.

IQKeyboardManager为您完成此操作,无需代码行,只需将相关源文件拖放到项目即可。IQKeyboardManager还支持Device OrientationAutomatic UIToolbar ManagementkeyboardDistanceFromTextField等等。

enter image description here

在此处输入图片说明

Here is the Control Flow Chart: Control Flow Chart

这是控制流程图: 控制流程图

Step1:-Added global notifications of UITextField, UITextView, and UIKeyboardin a singleton class. I called it IQKeyboardManager.

第一步: -增加了全球的通知UITextFieldUITextViewUIKeyboard在一个单独的类。我称之为IQKeyboardManager

Step2:-If found UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotificationor UITextViewTextDidBeginEditingNotificationnotifications, then try to get topMostViewControllerinstance from the UIWindow.rootViewControllerhierarchy. In order to properly uncover UITextField/UITextViewon it, topMostViewController.view's frame needs to be adjusted.

第二步: -如果找到UIKeyboardWillShowNotificationUITextFieldTextDidBeginEditingNotificationUITextViewTextDidBeginEditingNotification通知,然后尝试获得topMostViewController从实例UIWindow.rootViewController层次结构。为了正确地揭开UITextField/UITextView在它上面,topMostViewController.view需要调整 的框架。

Step3:-Calculated expected move distance of topMostViewController.viewwith respect to first responded UITextField/UITextView.

步骤 3:-计算topMostViewController.view相对于第一响应的预期移动距离UITextField/ UITextView

Step4:-Moved topMostViewController.view.frameup/down according to the expected move distance.

第四步: -感动topMostViewController.view.frame向上/根据预期的移动距离了。

Step5:-If found UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotificationor UITextViewTextDidEndEditingNotificationnotification, then again try to get topMostViewControllerinstance from the UIWindow.rootViewControllerhierarchy.

第五步: -如果找到UIKeyboardWillHideNotificationUITextFieldTextDidEndEditingNotificationUITextViewTextDidEndEditingNotification通知,然后再次尝试获得topMostViewController从实例UIWindow.rootViewController层次结构。

Step6:-Calculated disturbed distance of topMostViewController.viewwhich needs to be restored to it's original position.

Step6:-计算出topMostViewController.view需要恢复到原来位置的扰动距离。

Step7:-Restored topMostViewController.view.framedown according to the disturbed distance.

Step7:-topMostViewController.view.frame根据干扰距离还原。

Step8:-Instantiated singleton IQKeyboardManagerclass instance on app load, so every UITextField/UITextViewin the app will adjust automatically according to the expected move distance.

Step8:-在应用程序加载时实例化单例IQKeyboardManager类实例,因此应用程序中的每个UITextField/UITextView将根据预期的移动距离自动调整。

That's all

就这样

回答by Mars

How about the official solution: Moving Content That Is Located Under the Keyboard

官方解决方案如何:移动位于键盘下方的内容

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:

  1. Get the size of the keyboard.
  2. Adjust the bottom content inset of your scroll view by the keyboard height.
  3. Scroll the target text field into view.

调整您的内容通常涉及临时调整一个或多个视图的大小并定位它们,以便文本对象保持可见。使用键盘管理文本对象的最简单方法是将它们嵌入到 UIScrollView 对象(或其子类之一,如 UITableView)中。当键盘显示时,您所要做的就是重置滚动视图的内容区域并将所需的文本对象滚动到位。因此,为了响应 UIKeyboardDidShowNotification,您的处理程序方法将执行以下操作:

  1. 获取键盘的大小。
  2. 通过键盘高度调整滚动视图的底部内容插入。
  3. 将目标文本字段滚动到视图中。
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
            selector:@selector(keyboardWasShown:)
            name:UIKeyboardDidShowNotification object:nil];

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

}

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

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

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

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;
}

回答by Boobalan

I have face the same issue in UITableViewtextField cells. I solve this issue by implementing following method to listen the keyboard notification.

我在UITableViewtextField 单元格中遇到了同样的问题。我通过实现以下方法来收听键盘通知来解决这个问题。

Observer for the notifications here:

此处通知的观察者:

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

Handle those notification by using below function:

使用以下函数处理这些通知:

(void)keyboardWasShown:(NSNotification*)aNotification 
(void)keyboardWillBeHidden:(NSNotification*)aNotification 

回答by stebooks

To expand on Amagrammer answer, here is a sample class:

为了扩展 Amagrammer 的答案,这里有一个示例类:

LoginViewController.h

登录视图控制器.h

@interface LoginViewController : UIViewController <UITextFieldDelegate> {

}

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

Notice we are implementing the "UITextFieldDelegate"

注意我们正在实现“UITextFieldDelegate”

LoginViewController.m

登录视图控制器.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];
}

回答by Justin Domnitz

Below is a swift version of Amagrammer's answer. Also, a variation using the UIKeyboardWillShowNotification event since I needed to know the keyboards size before moving the view out of the way.

以下是 Amagrammer 答案的快速版本。此外,使用 UIKeyboardWillShowNotification 事件的变体,因为我需要在将视图移开之前知道键盘大小。

var keyboardHeight:CGFloat = 0

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

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

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

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

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

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

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

回答by Aruna

Check this out. No hassle for you.

看一下这个。没有你的麻烦。

This solution is very neat. All you have to do is to add your textfields in a UIScrollViewand change its class to TPKeyboardAvoidingScollView, if you are using storyboards. The scroll view is extended in such a way that it would detect when keyboard is visible and will move itself above keyboard at a reasonable distance. It is perfect solution because its independent of your UIViewController. Every necessary thing is done within the the above mentioned class. Thanks Michael Tyson et all.

这个解决方案非常简洁。如果您使用故事板,您所要做的就是在 a 中添加文本字段UIScrollView并将其类更改为TPKeyboardAvoidingScollView。滚动视图以这样一种方式扩展,它会检测键盘何时可见,并将在键盘上方移动一段合理的距离。它是完美的解决方案,因为它独立于您的UIViewController. 所有必要的事情都在上述类中完成。感谢迈克尔泰森等。

TPKeyboardAvoiding

TPKeyboardAvoiding

回答by GargantuChet

There was a great walkthrough at editing textfields without obscuring(link dead now, here's a Wayback link: https://web.archive.org/web/20091123074029/http://acts-as-geek.blogspot.com/2009/11/editing-textfields-without-obscuring.html). It shows how to move an existing UIViewonto a UIScrollView, and to scroll it automatically when the keyboard appears.

不遮挡的情况下编辑文本字段有一个很好的演练(链接现在已经失效,这是一个 Wayback 链接:https://web.archive.org/web/20091123074029/http: //acts-as-geek.blogspot.com/2009/ 11/editing-textfields-without-obscuring.html)。它显示了如何将现有内容移动UIViewUIScrollView,并在键盘出现时自动滚动它。

I've updated it a bit to calculate the correct height for the UIScrollViewwhen there are controls (such as a UITabBar) below the UIScrollBar. See post updating uiview.

我已经更新了它一下来计算正确的高度UIScrollView时,有控件(如UITabBar以下)UIScrollBar。请参阅更新 uiview 的帖子

回答by Ethan Parker

Here's a solution using Xcode5, iOS7:

这是使用Xcode5,iOS7的解决方案:

Use the UITextfieldDelegate and animation blocks.

使用 UITextfieldDelegate 和动画块。

This is nearly all the code for the ViewController but I wanted to include the delegate code for those still somewhat unfamiliar with the delegate pattern (like me). I also included code to hide the keyboard when you tap away from the textview.

这几乎是 ViewController 的所有代码,但我想包括那些仍然有点不熟悉委托模式的人(像我一样)的委托代码。我还包含了当您从文本视图中点击时隐藏键盘的代码。

You can move the views(buttons, textfields, etc) as high as you'd like just make sure to put them back in place (+100 then later -100).

您可以将视图(按钮、文本字段等)移动到您想要的高度,只需确保将它们放回原位(+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];
}