从文本字段跳转到文本字段时移动视图

时间:2013-04-19 17:42:52

标签: iphone xcode4.6

我在滚动视图中有一个带有几个文本字段的表单。我试图解决键盘隐藏一些文本字段的问题,我部分地做了。当我点击每个单独的领域时,至少它运作良好。我使用了推荐的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按钮(代替或返回),而最后一个字段有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按钮的顶部栏) - 缺少的代码在此方法中:< / p>

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

好的,正如我所提到的,即使键盘大小(标准iOS与我的自定义视图)的高度不同,查看调整在点击单个文本字段(然后解除键盘)时效果也很好。我也可以成功浏览所有文本字段,点击下一步按钮。

以下是我的问题:

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

也许一对经验丰富的眼睛会发现我的错误,因为我一直在摧毁我的眼睛,寻找过去2天的解决方案..

谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用UITextField委托。每当用户开始在任何文本字段中编辑其委托时,您可以使用

更改scrollview偏移
- (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];

希望这适合你。

答案 1 :(得分:0)

https://github.com/simonbs/BSKeyboardControls

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

enter image description here

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

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

答案 2 :(得分: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。完成此操作后,在移动到相关字段时会检测到键盘(或自定义视图),而不是在远离它时检测到。

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

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

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

希望这有助于某人。