使用iOS SDK:

我有一个带UITextFields的UIView,可以启动键盘。我需要它能够:

启动键盘后,允许滚动UIScrollView的内容以查看其他文本字段自动“跳转”(通过向上滚动)或缩短

我知道我需要一个UIScrollView。我已经尝试将UIView的类更改为UIScrollView,但仍然无法上下滚动文本框。

我需要UIView和UIScrollView吗?一个在另一个里面吗?

要自动滚动到活动文本字段,需要执行哪些操作?

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

注意:我使用的UIView(或UIScrollView)是由一个选项卡(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
}

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


当前回答

这可以通过以下代码行使用约束简单地实现

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]];
}

- (void)viewDidDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewDidDisappear:animated];
}

- (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info {
    CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat height = keyboardFrame.size.height;
    self.constraintToAdjust.constant = height;        UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
    UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState;
    if (animationCurve == UIViewAnimationCurveEaseIn) {
        animationOptions |= UIViewAnimationOptionCurveEaseIn;
    }
    else if (animationCurve == UIViewAnimationCurveEaseInOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseInOut;
    }
    else if (animationCurve == UIViewAnimationCurveEaseOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseOut;
    }
    else if (animationCurve == UIViewAnimationCurveLinear) {
        animationOptions |= UIViewAnimationOptionCurveLinear;
    }
    [UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{
        [self.view layoutIfNeeded];
    }                completion:nil];
}

其他回答

我已经组装了一个通用的UIScrollView、UITableView甚至UICollectionView子类,它负责将其中的所有文本字段移到键盘之外。

当键盘即将出现时,子类将找到即将被编辑的子视图,并调整其框架和内容偏移,以确保该视图可见,并使用与键盘弹出窗口匹配的动画。当键盘消失时,它会恢复原来的大小。

它基本上可以与任何设置一起使用,无论是基于UITableView的界面,还是由手动放置的视图组成的界面。

这里是:将文本字段移出键盘的解决方案

我使用Swift和自动布局(但不能评论之前的Swift答案);以下是我在没有滚动视图的情况下的操作方法:

我在IB中使用字段之间的垂直约束来布局表单,以分隔它们。我在容器视图的最顶部字段中添加了一个垂直约束,并为此创建了一个出口(下面代码中的topSpaceForFormConstraint)。所有需要的就是更新这个约束,这是我在动画块中为一个漂亮的软运动所做的。当然,高度检查是可选的,在这种情况下,我只需要对最小的屏幕尺寸进行检查。

这可以使用任何常用的textFieldDidBegginEditing或keyboardWillShow方法调用。

func setFormHeight(top: CGFloat)
{
    let height = UIScreen.mainScreen().bounds.size.height

    // restore text input fields for iPhone 4/4s
    if (height < 568) {
        UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: {
            self.topSpaceForFormConstraint.constant = top
            self.view.layoutIfNeeded()
            }, completion: nil)
    }

}

请遵循以下步骤,这可能会有所帮助。放置一个视图,然后将文本字段放在该视图上,并在键盘弹出时通过代理检测事件,此时立即向上设置视图动画(您也可以为该视图指定一些位置),然后视图将向上移动到该位置。对向下设置视图动画执行相同的操作。

谢谢

这是我为特定布局想出的破解方案。此解决方案与Matt Gallagher的解决方案相似,即将一个部分滚动到视图中。我还是iPhone开发的新手,不熟悉布局的工作原理。因此,这个黑客。

我的实现需要支持在字段中单击时滚动,以及用户在键盘上选择下一个时滚动。

我有一个UIView,身高775。控件基本上以3人一组的方式分布在一个大的空间中。我最终得到了以下IB布局。

UIView -> UIScrollView -> [UI Components]

黑客来了

我将UIScrollView的高度设置为比实际布局(1250)大500个单位。然后,我创建了一个数组,其中包含我需要滚动到的绝对位置,以及一个基于IB标记号获取它们的简单函数。

static NSInteger stepRange[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};

NSInteger getScrollPos(NSInteger i) {
    if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
        return 0 ;
    return stepRange[i] ;
}

现在,您需要做的就是在textFieldDidBeginEditing和textFieldShouldReturn中使用以下两行代码(如果要创建下一个字段导航,则使用后者)

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;

一个例子。

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
    [self.scrollView setContentOffset:point animated:YES] ;
}


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

    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];

    if (nextResponder) {
        [nextResponder becomeFirstResponder];
        CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
        [self.scrollView setContentOffset:point animated:YES] ;
    }
    else{
        [textField resignFirstResponder];
    }

    return YES ;
}

此方法不像其他方法那样“向后滚动”。这不是必需的。同样,这是一个相当“高大”的UIView,我没有时间学习内部布局引擎。

有这么多的解决方案,但我花了几个小时才开始工作。因此,我将此代码放在这里(只需粘贴到项目中,无需进行任何修改):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

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

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

- (void)keyboardWillShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

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

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

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

P.S:我希望这段代码能帮助某人快速达到预期效果。(Xcode 4.5)