当键盘出现时,如何使UITextField向上移动?

使用iOS SDK:

我有一个带有UITextFieldUIViewUITextField键盘。 我需要它能够:

  • 键盘启动后,允许滚动UIScrollView的内容以查看其他文本字段

  • 自动“跳转”(通过滚动)或缩短

  • 我知道我需要一个UIScrollView 。 我试过将UIView的类更改为UIScrollView但我仍然无法向上或向下滚动文本框。

    我是否需要UIViewUIScrollView ? 一个人进入另一个吗?

    需要执行什么才能自动滚动到活动文本字段?

    理想情况下,尽可能多的组件设置将在Interface Builder中完成。 我只想编写需要它的代码。

    注意:我正在使用的UIView (或UIScrollView )由一个tabbar( 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
    }
    

    但是,这不会自动“向上移动”或将可见区域中的较低文本字段居中,这正是我真正想要的。


  • 如果您现在拥有的内容不适合iPhone屏幕,则只需要一个ScrollView 。 (如果您将ScrollView添加为组件的超级视图,只是为了让TextField在键盘出现时向上滚动,则不需要它。)

  • 为了显示没有被键盘隐藏的textfields ,标准方法是在显示键盘时向上/向下移动具有文本字段的视图。

  • 以下是一些示例代码:

    #define kOFFSET_FOR_KEYBOARD 80.0
    
    -(void)keyboardWillShow {
        // Animate the current view out of the way
        if (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
        else if (self.view.frame.origin.y < 0)
        {
            [self setViewMovedUp:NO];
        }
    }
    
    -(void)keyboardWillHide {
        if (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
        else if (self.view.frame.origin.y < 0)
        {
            [self setViewMovedUp:NO];
        }
    }
    
    -(void)textFieldDidBeginEditing:(UITextField *)sender
    {
        if ([sender isEqual:mailTf])
        {
            //move the main view, so that the keyboard does not hide it.
            if  (self.view.frame.origin.y >= 0)
            {
                [self setViewMovedUp:YES];
            }
        }
    }
    
    //method to move the view up/down whenever the keyboard is shown/dismissed
    -(void)setViewMovedUp:(BOOL)movedUp
    {
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.3]; // if you want to slide up the view
    
        CGRect rect = self.view.frame;
        if (movedUp)
        {
            // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
            // 2. increase the size of the view so that the area behind the keyboard is covered up.
            rect.origin.y -= kOFFSET_FOR_KEYBOARD;
            rect.size.height += kOFFSET_FOR_KEYBOARD;
        }
        else
        {
            // revert back to the normal state.
            rect.origin.y += kOFFSET_FOR_KEYBOARD;
            rect.size.height -= kOFFSET_FOR_KEYBOARD;
        }
        self.view.frame = rect;
    
        [UIView commitAnimations];
    }
    
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        // register for keyboard notifications
        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        // unregister for keyboard notifications while not visible.
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
    }
    

    我在使用由多个UITextFields组成的UIScrollView遇到了很多问题,其中一个或多个UITextFields在被编辑时会被键盘遮挡。

    如果您的UIScrollView没有正确滚动,请注意以下UIScrollView

    1)确保您的contentSize大于UIScrollView框架大小。 理解UIScrollViews的方法是UIScrollView就像contentSize中定义的内容的查看窗口。 所以当为了让UIScrollview在任何地方滚动时,contentSize必须大于UIScrollView 。 否则,由于contentSize中定义的所有内容都已经可见,因此不需要滚动。 顺便说一句,默认contentSize = CGSizeZero

    2)现在你明白了UIScrollView真的是你的“内容”的窗口,确保键盘不会遮挡你的UIScrollView's查看“窗口”的方法是调整UIScrollView大小,这样当键盘出现时,你将UIScrollView窗口调整为原来的UIScrollView frame.size.height减去键盘的高度。 这将确保您的窗户只有那个小的可视区域。

    3)这里有一个问题:当我第一次实现这个时,我想我必须得到已编辑文本字段的CGRect并调用UIScrollView's scrollRecToVisible方法。 我通过调用scrollRecToVisible方法实现了UITextFieldDelegate方法textFieldDidBeginEditing 。 这实际上与一个奇怪的副作用,即滚动将UITextField捕捉到位。 最长的时间我无法弄清楚它是什么。 然后我注释掉了textFieldDidBeginEditing委托方法,它都可以工作!!(???)。 事实证明,我相信UIScrollView实际上隐含地将当前编辑的UITextField隐式UITextField入可视窗口。 我的UITextFieldDelegate方法的实现和对scrollRecToVisible后续调用是多余的,并且是造成奇怪副作用的原因。

    因此,这里是正常滚动的步骤UITextFieldUIScrollView到位键盘出现时。

    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    
    - (void)viewDidLoad 
    {
        [super viewDidLoad];
    
        // register for keyboard notifications
        [[NSNotificationCenter defaultCenter] addObserver:self 
                                                 selector:@selector(keyboardWillShow:) 
                                                     name:UIKeyboardWillShowNotification 
                                                   object:self.view.window];
        // register for keyboard notifications
        [[NSNotificationCenter defaultCenter] addObserver:self 
                                                 selector:@selector(keyboardWillHide:) 
                                                     name:UIKeyboardWillHideNotification 
                                                   object:self.view.window];
        keyboardIsShown = NO;
        //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
        CGSize scrollContentSize = CGSizeMake(320, 345);
        self.scrollView.contentSize = scrollContentSize;
    }
    
    - (void)keyboardWillHide:(NSNotification *)n
    {
        NSDictionary* userInfo = [n userInfo];
    
        // get the size of the keyboard
        CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    
    
        // resize the scrollview
        CGRect viewFrame = self.scrollView.frame;
        // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
        viewFrame.size.height += (keyboardSize.height - kTabBarHeight);
    
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [self.scrollView setFrame:viewFrame];
        [UIView commitAnimations];
    
        keyboardIsShown = NO;
    }
    
    - (void)keyboardWillShow:(NSNotification *)n
    {
        // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
        if (keyboardIsShown) {
            return;
        }
    
        NSDictionary* userInfo = [n userInfo];
    
        // get the size of the keyboard
        CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    
        // resize the noteView
        CGRect viewFrame = self.scrollView.frame;
        // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
        viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);
    
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [self.scrollView setFrame:viewFrame];
        [UIView commitAnimations];
        keyboardIsShown = YES;
    }
    
  • viewDidLoad注册键盘通知
  • 注销viewDidUnload的键盘nofit
  • 确保contentSize设置为大于UIScrollViewviewDidLoad
  • 当键盘存在时收缩UIScrollView
  • 当键盘消失时恢复UIScrollView
  • 使用伊娃来检测键盘是否已经显示在屏幕上,因为每次UITextField被选中时都会发送键盘通知,即使键盘已经存在以避免缩小UIScrollView当它已经缩小
  • 有一点需要注意的是,即使当您在另一个UITextField上选择了键盘时, UIKeyboardWillShowNotification也会触发。 我通过使用ivar来解决这个问题,以避免在键盘已经在屏幕上时调整UIScrollView大小。 当键盘已经存在时无意中调整UIScrollView大小将会是灾难性的!

    希望这段代码能够为您节省一些很多头痛的问题。


    正如文档中提供的那样,实际上最好使用Apple的实现。 但是,他们提供的代码是错误的。 将keyboardWasShown:发现的部分替换为下面的注释:

    NSDictionary* info = [aNotification userInfo];
    CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
    CGSize kbSize =keyPadFrame.size;
    CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
    CGRect aRect = self.view.bounds;
    aRect.size.height -= (kbSize.height);
    
    CGPoint origin =  activeRect.origin;
    origin.y -= backScrollView.contentOffset.y;
    if (!CGRectContainsPoint(aRect, origin)) {
        CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
        [backScrollView setContentOffset:scrollPoint animated:YES];
    }
    

    Apple代码的问题是:(1)他们总是计算该点是否在视图的框架内,但它是一个ScrollView ,因此它可能已经滚动并且需要考虑该偏移量:

    origin.y -= scrollView.contentOffset.y
    

    (2)他们将contentOffset移动了键盘的高度,但我们想要的是相反的(我们想要将contentOffset移动到屏幕上可见的高度,而不是那个)。

    activeField.frame.origin.y-(aRect.size.height)
    
    链接地址: http://www.djcxy.com/p/27495.html

    上一篇: How can I make a UITextField move up when the keyboard is present?

    下一篇: How to remove Chutzpah from project to not show result in test explorer?