0

我有一个滚动视图上有几个文本字段的表单。我试图解决键盘隐藏一些文本字段的问题,我部分做到了。至少当我点击每个单独的字段时效果很好。我使用了推荐的 Apple 方法:

我已经在 viewDidLoad 中注册了键盘通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window];                                       
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window];

我正在跟踪活动文本字段:

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

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

当键盘出现时,我正在向上滚动视图:

- (void)keyboardWillShow:(NSNotification *)aNotification {
    // Get the size of the keyboard
    NSDictionary* info = [aNotification userInfo];
    keyboardHeight = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height;

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

    // If active text field is hidden by keyboard, scroll it so it's visible
    CGRect aRect = self.view.frame;
    aRect.size.height -= keyboardHeight + 44 + 44; // Compensates for Navbar and text field height
    if (!CGRectContainsPoint(aRect, activeTextField.frame.origin) ) {
        [scrollView scrollRectToVisible:activeTextField.frame animated:YES];
    }
}

然后,当键盘隐藏时,我将视图滚动回默认值(我不会粘贴代码,因为它工作正常)。

但是,在我的 5 个文本字段中,前 4 个在键盘上有一个 Next 按钮(而不是 Return),而最后一个字段有 Done。这个想法是我希望用户从一个文本字段跳转到另一个文本字段(在我的情况下,一个方向就足够了)。所以,我也实现了一个 UITextField 委托方法来处理它:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if (textField == firstNameTextField) {
        [lastNameTextField becomeFirstResponder];

    } else if (textField == lastNameTextField) {
        [countryTextField becomeFirstResponder];

    } else if (textField == cityTextField) {
        [zipCodeTextField becomeFirstResponder];

    } else if (textField == zipCodeTextField) {
        [zipCodeTextField resignFirstResponder];
    }
    return NO;
}

上面的中间文本字段被跳过,因为对于该文本字段,我使用了不同的输入类型(带有 UIPickerView 的自定义视图和顶部带有 Next 按钮的栏) - 缺少的代码在此方法中:

- (IBAction)goToNextTextField:(id)sender {
    [cityTextField becomeFirstResponder];
}

好的,正如我已经提到的,即使键盘尺寸(标准 iOS 与我的自定义视图)的高度不同,在点击单个文本字段(然后关闭键盘)时视图调整效果很好。我还可以通过点击下一步按钮成功浏览所有文本字段。

这是我的问题:

  • 当点击 Next 时,如果键盘没有改变(例如,从字段 4 到 5,两者都使用标准键盘),我的 keyboardWillShow: 方法没有被调用,NSLog 调试器将 keyboardHeight 显示为 0,但视图却不可预测地向上移动。
  • 此外,当在字段 3(使用自定义输入视图的字段)之间导航时,不会重新计算键盘高度。我已经尝试注册到 UIKeyboardDidChangeFrameNotification 和 UIKeyboardWillChangeFrameNotification (指向keyboardWillShow:方法),但没有多大成功。值得注意的是,我确实在控制台中看到了keyboardHeight 正在发生变化,但它通常滞后一步,即keyboardHeight 在我离开现场时更新,而不是在它成为FirstResponder 时更新。

也许一双有经验的眼睛会发现我的错误,因为过去两天我一直在摧毁我的一双眼睛寻找解决方案。

谢谢!

4

3 回答 3

1

您可以使用 UITextField 委托。每当用户开始在任何文本字段中编辑其委托时,您都可以使用更改滚动视图偏移量

- (void)scrollViewToCenterOfScreen:(UIView *)theView 
{  
    CGFloat viewCenterY = theView.center.y;  
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];  

    CGFloat availableHeight = applicationFrame.size.height - 200;            // Remove area covered by keyboard  

    CGFloat y = viewCenterY - availableHeight / 2.0;  
    if (y < 0) 
    {  
        y = 0;  
    }  
    [scrollView  setContentOffset:CGPointMake(0, y+20) animated:YES]; 
}

所以在 TextField 委托中你可以设置

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if([textField isEqual:textfield1])
    {
         [self scrollViewToCenterOfScreen:textfield1];

    }
    else if([textField isEqual:textfield2])
    {
         [self scrollViewToCenterOfScreen:textfield2];

    }

return YES;
}

当用户按下完成或返回按钮时,您可以将偏移更改为 (0,0)

    [scrollView setContentOffset:CGPointMake(0, 0) animated:YES];

希望这对你有用。

于 2013-04-19T19:33:01.030 回答
0

https://github.com/simonbs/BSKeyboardControls

像这样编辑文本字段时,此控件可以在键盘上方显示工具栏

在此处输入图像描述

===========================================

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    if (textField == firstNameTextField) {
         //move to firstNameTextField

    } else if (textField == lastNameTextField) {
         //move to lastNameTextField

    } else if (textField == cityTextField) {
         //move to cityTextField

    } else if (textField == zipCodeTextField) {
         //move to zipCodeTextField
    }
    return NO;
}
于 2013-04-19T17:44:25.070 回答
0

我最终实施了一个适合我的解决方案。这是 Apple 推荐的方法、在这些论坛和我自己的论坛上找到的几个解决方案的混合体。

首先,在视图控制器 .h 文件中注册为 UITextFieldDelegate。

然后在 viewDidLoad 注册键盘通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:self.view.window];

不要忘记在 viewDidUnload 方法中取消注册(removeObserver :)。

让您的应用程序知道哪个文本字段当前处于活动状态:

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

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

当您的应用程序收到键盘将显示的通知时,它会调用此方法:

- (void)keyboardWillShow:(NSNotification *)aNotification {

    keyboardHeight = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

    [scrollView setFrame:CGRectMake(scrollView.frame.origin.x, 
                                    scrollView.frame.origin.y, 
                                    scrollView.frame.size.width, 
                                    scrollView.frame.size.height - keyboardHeight)];

    [self moveViewWithKeyboard];
}

我在这里所做的只是将我的 scrollView 框架的大小减小键盘的大小。之后,我调用我的 moveViewWithKeyboard: 方法,该方法将使活动视图可见。

有趣的是,为了解决检测到正确的键盘高度为时已晚的问题(阅读我上面的原始问题),我不得不使用 UIKeyboardFrameEndUserInfoKey 参数更改键盘高度检测行中的参数 UIKeyboardFrameBeginUserInfoKey 。这样做之后,在移动到相关字段时会检测到键盘(或自定义视图),而不是在离开时检测到键盘(或自定义视图)。

当然,当键盘隐藏时,我必须恢复原始视图框架(请注意,我仍在调用 moveViewWithKeyboard: 方法,并将 nil 作为参数):

- (void)keyboardWillHide:(NSNotification *)aNotification {

    [scrollView setFrame:CGRectMake(scrollView.frame.origin.x, 
                                    scrollView.frame.origin.y, 
                                    scrollView.frame.size.width, 
                                    scrollView.frame.size.height + keyboardHeight)];

    [self moveViewWithKeyboard];
}

当未触发键盘隐藏/显示时,我还添加了移动视图的调用。当我从文本字段跳转到以系统键盘作为输入的文本字段时会发生这种情况,因此它既不会隐藏也不会再次显示(并且不会发出通知来触发委托方法)。

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

    if (textField == firstNameTextField) {
        [lastNameTextField becomeFirstResponder];
    } else if (textField == lastNameTextField) {
        [countryTextField becomeFirstResponder];
    } else if (textField == cityTextField) {
        [zipCodeTextField becomeFirstResponder];
    } else if (textField == zipCodeTextField) {
        [zipCodeTextField resignFirstResponder];
    }

    [self moveViewWithKeyboard:nil];

    return NO;
}

最后是我移动视图的方法:

- (void)moveViewWithKeyboard {

    if (activeTextField) {
        [scrollView scrollRectToVisible:activeTextField.frame animated:YES];
    } else {
        [scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
    }
}

请注意,当没有文本字段作为参数传递时(即没有文本字段处于活动状态),视图将滚动到其原始位置。

希望这可以帮助某人。

于 2013-05-07T21:29:28.990 回答