使用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
}

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


当前回答

有很多答案可以告诉我们这个方法。我采取了相同的方法,但实施效果不佳。

这是基本想法。我修改了keyboardWasShown方法。

{
// Obtain keyboard Info
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

// Obtain ScrollView Info w.r.t. top View
CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil];

// Depending upon your screen Ui, Scroll View's bottom edge might be at some offset from screen's bottom
// Calculate the exact offset
int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.origin.y + scrollViewRect.size.height);
int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset;


// We may also need to consider the Insets if already present with ScrollView. Let's keep it simple for now
// But we should store these, so that we can restore the Insets when Keyboard is gone
// origInsets = self.scrollView.contentInset;

// Set the new Insets for ScrollView
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

// Visible frame (not overlapped by Keyboard)
CGRect visibleFrame = self.view.frame;
visibleFrame.size.height -= keyboardRect.size.height;

// Get the Rect for Textfield w.r.t self.view
CGRect activeFieldFrame = self.activeField.frame;
activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView];

// Check if the TextField is Visible or not
if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) {
    // Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View
    [self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}

}

并添加此方法来初始化activeField

- (IBAction)textFieldDidBeginEditing:(UITextField *)sender
{
self.activeField = sender;
}

其他回答

如果该文本字段位于表的单元格中(即使table.scrollable=NO),也可以轻松自动完成。

注意:桌子的位置和大小必须合理。例如:如果桌子的y位置是从视图底部算起的100,那么300高的键盘将覆盖整个桌子。如果表的高度为10,并且当键盘出现时,其中的文本字段必须向上滚动100才能可见,那么该文本字段将超出表的范围。

仅使用文本字段:

1a)使用界面生成器:选择所有文本字段=>编辑=>嵌入=>滚动视图

1b)在UIScrollView中手动嵌入文本字段,称为scrollView

2) 设置UITextFieldDelegate

3) 设置每个textField.delegate=self;(或在Interface Builder中建立连接)

4) 复制/粘贴:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}

我想延长@sumanthkodi的回答。

正如一些人所说,他的方法在较新的实现中不起作用,因为当您使用约束时,UIView无法移动。

我编辑了如下代码(并移植到Swift 2.0),希望它能帮助一些人:


1) 参照要向上移动的视图的垂直约束:

@IBOutlet var viewConstraint: NSLayoutConstraint!

确保在脚本中使用约束引用此变量。

2) 添加委托并实现侦听器。这是与之前相同的实现:

class YourViewController: UIViewController, UITextFieldDelegate {

    ...

    func textFieldDidBeginEditing(textField: UITextField) {
        animateTextField(textField, up: true)
    }

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

    ...

}

3) 将动画方法animateTextField添加到YourViewController类。根据需要设置临时约束值。

func animateTextField(textfield: UITextField, up: Bool) {

    let originalConstraint = 50
    let temporaryConstraint = 0
    let movementDuration = 0.3

    let constraint = CGFloat(up ? temporaryConstraint : originalConstraint)

    containerViewConstraint.constant = constraint
    UIView.animateWithDuration(movementDuration) {
        self.view.layoutIfNeeded()
    }

}

如果文本字段未完全或部分隐藏,则我们不应更改任何内容。我们应该计算隐藏的精确相交区域(键盘的框架和文本字段的框架),然后我们应该更改视图的框架。这里我给出了一个完整的例子。声明3个变量

#定义衬垫10@接口PKViewController()@属性(非原子,赋值)CGRect-originalViewFrame//原始视图的框架@属性(非原子,强)UITextField*activeTextField;//当前文本字段@属性(非原子,赋值)CGRect keyBoardRect;//安全板覆盖面积@完

存储原始帧

- (void)viewDidLoad {
    [super viewDidLoad];
    _originalViewFrame = self.view.frame;
}

将视图控制器添加为键盘通知的观察者

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

移除观察者

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

当键盘出现时存储键盘覆盖的区域,当键盘消失时将其设置为CGRectZero

- (void)keyboardWasShown:(NSNotification *)notification{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    _keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height);
    [self moveTextFieldUP];

}
- (void) keyboardWillHide:(NSNotification *)notification{
    _keyBoardRect = CGRectZero;
    [self setDefaultFrame];
}

存储活动文本字段

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    _activeTextField = textField;
//When keyboard is already present but the textfield is hidden. Case:When return key of  keyboard makes the next textfield as first responder
    if (!CGRectIsEmpty(_keyBoardRect)) { 
        [self moveTextFieldUP];
    }
    return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
}

现在我们应该改变视图的框架

- (void)moveTextFieldUP{
    CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.origin.y, _activeTextField.frame.size.width, _activeTextField.frame.origin.y+_activeTextField.frame.size.height);
    if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) {
        CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect);
        CGFloat newY = _originalViewFrame.origin.y - intersectRect.size.height;
        CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height;
        CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING);
        [UIView animateWithDuration:0.3 animations:^{
            [self.view setFrame:newFrame];
        }];

        NSLog(@"Intersect");
    }
}
- (void)setDefaultFrame {
    [UIView animateWithDuration:0.3 animations:^{
        [self.view setFrame:_originalViewFrame];
    }];
}

从Dune Buggy的回答中得到了参考。根据TextField的位置向上滚动视图。因为现有的答案是滚动屏幕的整个视图,所以我需要根据文本字段的框架滚动视图。

键盘WillShow

@objc func keyboardWillShow(notification: NSNotification) {
    
    guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
        
        // if keyboard size is not available for some reason, don't do anything
        return
    }
    let keyboardFrame = keyboardSize
    
    let maxheightScreen = self.view.frame
    
    
    if (self.txtEmail.frame.origin.y + ((self.txtEmail.superview)!.frame.maxY) + keyboardSize.height) >= maxheightScreen.size.height{
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= (keyboardFrame.height - (self.txtEmail.frame.maxY + 120)) // Here i added 120 additional height for my additional view space
        }
    }
}

键盘将隐藏

@objc func keyboardWillHide(notification: NSNotification) {
    
    guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
        // if keyboard size is not available for some reason, don't do anything
        return
    }
    
    let keyboardFrame = keyboardSize
    
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y += (keyboardFrame.height - (self.txtEmail.frame.maxY + 120))
    }
}