获取 UITableView 滚动到选定的 UITextField 并避免被键盘隐藏

发布于 2024-10-21 04:50:10 字数 2438 浏览 4 评论 0原文

我在 UIViewController(不是 UITableViewController)上的表视图中有一个 UITextField。 如果表格视图位于 UITableViewController 上,表格将自动滚动到正在编辑的 textField 以防止其被键盘隐藏。但在 UIViewController 上则不然。

我已经尝试了几天阅读多种方法来尝试实现这一目标,但我无法让它发挥作用。实际滚动的最接近的东西是:

-(void) textFieldDidBeginEditing:(UITextField *)textField {

// SUPPOSEDLY Scroll to the current text field

CGRect textFieldRect = [textField frame];
[self.wordsTableView scrollRectToVisible:textFieldRect animated:YES];

}

但是,这只会将表格滚动到最上面的行。 看似简单的任务,却经历了几天的挫折。

我正在使用以下内容来构造 tableView 单元格:

- (UITableViewCell *)tableView:(UITableView *)aTableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]];

UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] 
        initWithStyle:UITableViewCellStyleDefault 
        reuseIdentifier:identifier] autorelease];

        cell.accessoryType = UITableViewCellAccessoryNone;

        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)];

        theTextField.adjustsFontSizeToFitWidth = YES;
        theTextField.textColor = [UIColor redColor];
        theTextField.text = [textFieldArray objectAtIndex:indexPath.row];
        theTextField.keyboardType = UIKeyboardTypeDefault;
        theTextField.returnKeyType = UIReturnKeyDone;
        theTextField.font = [UIFont boldSystemFontOfSize:14];
        theTextField.backgroundColor = [UIColor whiteColor];
        theTextField.autocorrectionType = UITextAutocorrectionTypeNo;
        theTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
        theTextField.clearsOnBeginEditing = NO;
        theTextField.textAlignment = UITextAlignmentLeft;

        //theTextField.tag = 0;
        theTextField.tag=indexPath.row;

        theTextField.delegate = self;

        theTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
        [theTextField setEnabled: YES];

        [cell addSubview:theTextField];

        [theTextField release];


}

return cell;
}

我怀疑如果我能以某种方式在 textFieldDidBeginEditing 方法中传递 indexPath.row ,我可以让 tableView 正确滚动吗?

任何帮助表示赞赏。

I have a UITextField in a table view on a UIViewController (not a UITableViewController).
If the table view is on a UITableViewController, the table will automatically scroll to the textField being edited to prevent it from being hidden by the keyboard. But on a UIViewController it does not.

I have tried for a couple of days reading through multiple ways to try to accomplish this and I cannot get it to work. The closest thing that actually scrolls is:

-(void) textFieldDidBeginEditing:(UITextField *)textField {

// SUPPOSEDLY Scroll to the current text field

CGRect textFieldRect = [textField frame];
[self.wordsTableView scrollRectToVisible:textFieldRect animated:YES];

}

However this only scrolls the table to the topmost row.
What seems like an easy task has been a couple of days of frustration.

I am using the following to construct the tableView cells:

- (UITableViewCell *)tableView:(UITableView *)aTableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]];

UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] 
        initWithStyle:UITableViewCellStyleDefault 
        reuseIdentifier:identifier] autorelease];

        cell.accessoryType = UITableViewCellAccessoryNone;

        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)];

        theTextField.adjustsFontSizeToFitWidth = YES;
        theTextField.textColor = [UIColor redColor];
        theTextField.text = [textFieldArray objectAtIndex:indexPath.row];
        theTextField.keyboardType = UIKeyboardTypeDefault;
        theTextField.returnKeyType = UIReturnKeyDone;
        theTextField.font = [UIFont boldSystemFontOfSize:14];
        theTextField.backgroundColor = [UIColor whiteColor];
        theTextField.autocorrectionType = UITextAutocorrectionTypeNo;
        theTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
        theTextField.clearsOnBeginEditing = NO;
        theTextField.textAlignment = UITextAlignmentLeft;

        //theTextField.tag = 0;
        theTextField.tag=indexPath.row;

        theTextField.delegate = self;

        theTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
        [theTextField setEnabled: YES];

        [cell addSubview:theTextField];

        [theTextField release];


}

return cell;
}

I suspect I can get the tableView to scroll properly if I can somehow pass the indexPath.row in the textFieldDidBeginEditing method?

Any help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

各自安好 2024-10-28 04:50:10

在我的应用程序中,我成功地使用了 contentInsetscrollToRowAtIndexPath 的组合,如下所示:

当您想要显示键盘时,只需在表格底部添加一个 contentInset 即可所需高度:

tableView.contentInset =  UIEdgeInsetsMake(0, 0, height, 0);

然后,您可以安全地使用

[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:cell_index inSection:cell_section] animated:YES];

通过添加 contentInset,即使您专注于最后一个单元格,tableView 仍然能够滚动。只需确保在关闭键盘时重置了 contentInset。

编辑:
如果您只有一个部分(可以将 cell_section 替换为 0),并使用 textView 标记来通知单元格行。

In my app, I have successfully used a combination of contentInset and scrollToRowAtIndexPath like this:

When you want to display the keyboard, just add a contentInset at the bottom with your table with desired height:

tableView.contentInset =  UIEdgeInsetsMake(0, 0, height, 0);

Then, you can safely use

[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:cell_index inSection:cell_section] animated:YES];

By adding the contentInset, even if you are focusing on the last cell the tableView will still be able to scroll. Just make sure that when you are dismissing the keyboard, you reset the contentInset.

EDIT:
If you have only one section (you can replace cell_section with 0) and the use the textView tag to inform the cell row.

贪了杯 2024-10-28 04:50:10

Swift

@objc private func keyboardWillShow(_ notification: Notification) {
    guard let userinfo = notification.userInfo else {
        return
    }

    guard
        let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let endFrame = (userinfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
        let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
            return
    }
    
    UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
        let edgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: endFrame.height, right: 0)
        self.scrollView.contentInset = edgeInsets
        self.scrollView.scrollIndicatorInsets = edgeInsets
    })
}

@objc private func keyboardWillHide(_ notification: Notification) {
    guard let userinfo = notification.userInfo else {
        return
    }

    guard
        let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
            return
    }
    
    UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
        let edgeInsets = UIEdgeInsets.zero
        self.scrollView.contentInset = edgeInsets
        self.scrollView.scrollIndicatorInsets = edgeInsets
    })
}


override func viewDidLoad() {
    super.viewDidLoad()
    
    // ...

    subscribeToKeyboardNotifications()
}

deinit {
    unsubscribeFromKeyboardNotifications()
}

private func subscribeToKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIWindow.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIWindow.keyboardWillHideNotification, object: nil)
}

private func unsubscribeFromKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillHideNotification, object: nil)
}

Objective C

- (void)keyboardWillShow:(NSNotification *)sender
{
    CGFloat height = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
    
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
        UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 0, height, 0);
        tableView.contentInset = edgeInsets;
        tableView.scrollIndicatorInsets = edgeInsets;
    } completion:nil];
}

- (void)keyboardWillHide:(NSNotification *)sender
{
    NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
        UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
        tableView.contentInset = edgeInsets;
        tableView.scrollIndicatorInsets = edgeInsets;
    } completion:nil];
}

并在 - (void)viewDidLoad

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

然后

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Swift

@objc private func keyboardWillShow(_ notification: Notification) {
    guard let userinfo = notification.userInfo else {
        return
    }

    guard
        let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let endFrame = (userinfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
        let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
            return
    }
    
    UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
        let edgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: endFrame.height, right: 0)
        self.scrollView.contentInset = edgeInsets
        self.scrollView.scrollIndicatorInsets = edgeInsets
    })
}

@objc private func keyboardWillHide(_ notification: Notification) {
    guard let userinfo = notification.userInfo else {
        return
    }

    guard
        let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
            return
    }
    
    UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
        let edgeInsets = UIEdgeInsets.zero
        self.scrollView.contentInset = edgeInsets
        self.scrollView.scrollIndicatorInsets = edgeInsets
    })
}


override func viewDidLoad() {
    super.viewDidLoad()
    
    // ...

    subscribeToKeyboardNotifications()
}

deinit {
    unsubscribeFromKeyboardNotifications()
}

private func subscribeToKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIWindow.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIWindow.keyboardWillHideNotification, object: nil)
}

private func unsubscribeFromKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillHideNotification, object: nil)
}

Objective C

- (void)keyboardWillShow:(NSNotification *)sender
{
    CGFloat height = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
    
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
        UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 0, height, 0);
        tableView.contentInset = edgeInsets;
        tableView.scrollIndicatorInsets = edgeInsets;
    } completion:nil];
}

- (void)keyboardWillHide:(NSNotification *)sender
{
    NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
        UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
        tableView.contentInset = edgeInsets;
        tableView.scrollIndicatorInsets = edgeInsets;
    } completion:nil];
}

And in - (void)viewDidLoad

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

Then

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
梦萦几度 2024-10-28 04:50:10

这是对 FunkyKat 答案的调整(非常感谢 FunkyKat!)。为了未来的 iOS 兼容性,不硬编码 UIEdgeInsetsZero 可能会有好处。

相反,我询问当前的插​​入值并根据需要调整底部值。

- (void)keyboardWillShow:(NSNotification *)sender {
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.height : kbSize.width;
    if (isIOS8()) height = kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = [[self tableView] contentInset];
        edgeInsets.bottom = height;
        [[self tableView] setContentInset:edgeInsets];
        edgeInsets = [[self tableView] scrollIndicatorInsets];
        edgeInsets.bottom = height;
        [[self tableView] setScrollIndicatorInsets:edgeInsets];
    }];
}

- (void)keyboardWillHide:(NSNotification *)sender {
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = [[self tableView] contentInset];
        edgeInsets.bottom = 0;
        [[self tableView] setContentInset:edgeInsets];
        edgeInsets = [[self tableView] scrollIndicatorInsets];
        edgeInsets.bottom = 0;
        [[self tableView] setScrollIndicatorInsets:edgeInsets];
    }];
}

This is a tweak to FunkyKat's answer (big thank you FunkyKat!). It would probably be beneficial to not hardcode UIEdgeInsetsZero for future iOS compatibility.

Instead, I ask for the current inset value and tweak the bottom value as needed.

- (void)keyboardWillShow:(NSNotification *)sender {
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.height : kbSize.width;
    if (isIOS8()) height = kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = [[self tableView] contentInset];
        edgeInsets.bottom = height;
        [[self tableView] setContentInset:edgeInsets];
        edgeInsets = [[self tableView] scrollIndicatorInsets];
        edgeInsets.bottom = height;
        [[self tableView] setScrollIndicatorInsets:edgeInsets];
    }];
}

- (void)keyboardWillHide:(NSNotification *)sender {
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = [[self tableView] contentInset];
        edgeInsets.bottom = 0;
        [[self tableView] setContentInset:edgeInsets];
        edgeInsets = [[self tableView] scrollIndicatorInsets];
        edgeInsets.bottom = 0;
        [[self tableView] setScrollIndicatorInsets:edgeInsets];
    }];
}
新人笑 2024-10-28 04:50:10

为了其他人遇到这个问题,我在这里发布了必要的方法:

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]];

    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc]  initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];

        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)];

        theTextField.keyboardType = UIKeyboardTypeDefault;
        theTextField.returnKeyType = UIReturnKeyDone;
        theTextField.clearsOnBeginEditing = NO;
        theTextField.textAlignment = UITextAlignmentLeft;

        // (The tag by indexPath.row is the critical part to identifying the appropriate
        // row in textFieldDidBeginEditing and textFieldShouldEndEditing below:)

        theTextField.tag=indexPath.row;

        theTextField.delegate = self;

        theTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
        [theTextField setEnabled: YES];

        [cell addSubview:theTextField];

        [theTextField release];

    }

    return cell;
}

-(void) textFieldDidBeginEditing:(UITextField *)textField {

    int z = textField.tag;                                              

    if (z > 4) {

        // Only deal with the table row if the row index is 5 
        // or greater since the first five rows are already 
        // visible above the keyboard   

        // resize the UITableView to fit above the keyboard

        self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,200.0);       

        // adjust the contentInset

        wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 10);        

        // Scroll to the current text field

        [wordsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:z inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

    }
}


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

    // Determine which row is being edited

    int z = textField.tag;  

    if (z > 4) {

        // resize the UITableView to the original size

        self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,416.0);       

        // Undo the contentInset
        wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);         

    }

    return YES;

}

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

    // Dismisses the keyboard when the "Done" button is clicked

    [textField resignFirstResponder];

    return YES;                                 

}

For the sake of anyone else running into this issue, I'm posting the necessary methods here:

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *identifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition: 0], [indexPath indexAtPosition:1]];

    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc]  initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];

        UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 10, 130, 25)];

        theTextField.keyboardType = UIKeyboardTypeDefault;
        theTextField.returnKeyType = UIReturnKeyDone;
        theTextField.clearsOnBeginEditing = NO;
        theTextField.textAlignment = UITextAlignmentLeft;

        // (The tag by indexPath.row is the critical part to identifying the appropriate
        // row in textFieldDidBeginEditing and textFieldShouldEndEditing below:)

        theTextField.tag=indexPath.row;

        theTextField.delegate = self;

        theTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
        [theTextField setEnabled: YES];

        [cell addSubview:theTextField];

        [theTextField release];

    }

    return cell;
}

-(void) textFieldDidBeginEditing:(UITextField *)textField {

    int z = textField.tag;                                              

    if (z > 4) {

        // Only deal with the table row if the row index is 5 
        // or greater since the first five rows are already 
        // visible above the keyboard   

        // resize the UITableView to fit above the keyboard

        self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,200.0);       

        // adjust the contentInset

        wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 10);        

        // Scroll to the current text field

        [wordsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:z inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

    }
}


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

    // Determine which row is being edited

    int z = textField.tag;  

    if (z > 4) {

        // resize the UITableView to the original size

        self.wordsTableView.frame = CGRectMake(0.0,44.0,320.0,416.0);       

        // Undo the contentInset
        wordsTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);         

    }

    return YES;

}

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

    // Dismisses the keyboard when the "Done" button is clicked

    [textField resignFirstResponder];

    return YES;                                 

}
肥爪爪 2024-10-28 04:50:10

我需要一个简单的解决方案,所以对我来说有帮助:

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        let pointInTable = textField.superview!.convert(textField.frame.origin, to: tableView)
        var tableVContentOffset = tableView.contentOffset
        tableVContentOffset.y = pointInTable.y
        if let accessoryView = textField.inputAccessoryView {
            tableVContentOffset.y -= accessoryView.frame.size.height
        }
        tableView.setContentOffset(tableVContentOffset, animated: true)
        return true;
    }

在此输入图像描述

I needed a simple solution so for me helped:

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        let pointInTable = textField.superview!.convert(textField.frame.origin, to: tableView)
        var tableVContentOffset = tableView.contentOffset
        tableVContentOffset.y = pointInTable.y
        if let accessoryView = textField.inputAccessoryView {
            tableVContentOffset.y -= accessoryView.frame.size.height
        }
        tableView.setContentOffset(tableVContentOffset, animated: true)
        return true;
    }

enter image description here

疯了 2024-10-28 04:50:10

尝试我的编码,这对 ypu 有帮助

tabelview.contentInset =  UIEdgeInsetsMake(0, 0, 210, 0);
[tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:your_indexnumber inSection:Your_section]
                 atScrollPosition:UITableViewScrollPositionMiddle animated:NO];

Try my coding, this will help for ypu

tabelview.contentInset =  UIEdgeInsetsMake(0, 0, 210, 0);
[tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:your_indexnumber inSection:Your_section]
                 atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
满天都是小星星 2024-10-28 04:50:10

苹果有一篇官方文章解释了如何像在 UITableViewController 中那样自然地做到这一点。我的 Stackoverflow 答案对此进行了解释,并提供了一个快速版本。

https://stackoverflow.com/a/31869898/1032179

Apple has an official post explaining how to do this naturally as they do in the UITableViewController. My Stackoverflow answer has this explained along with a swift version.

https://stackoverflow.com/a/31869898/1032179

时光是把杀猪刀 2024-10-28 04:50:10

您需要调整 tableView 本身的大小,使其不会位于键盘下方。

-(void) textFieldDidBeginEditing:(UITextField *)textField {

// SUPPOSEDLY Scroll to the current text field
self.worldsTableView.frame = CGRectMake(//make the tableView smaller; to only be in the area above the keyboard);
CGRect textFieldRect = [textField frame];
[self.wordsTableView scrollRectToVisible:textFieldRect animated:YES];

}

或者,您可以使用键盘通知;这工作得稍微好一些,因为你有更多的信息,并且在知道键盘何时出现方面更加一致:

//ViewDidLoad
[[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 {

}
- (void)keyboardWillHide:(NSNotification *)notification {

}

You need to resize the tableView itself so that it does not go under the keyboard.

-(void) textFieldDidBeginEditing:(UITextField *)textField {

// SUPPOSEDLY Scroll to the current text field
self.worldsTableView.frame = CGRectMake(//make the tableView smaller; to only be in the area above the keyboard);
CGRect textFieldRect = [textField frame];
[self.wordsTableView scrollRectToVisible:textFieldRect animated:YES];

}

Alternatively, you can use a keyboard notification; this works slightly better because you have more information, and is more consistent in terms of knowing when the keyboard is coming up:

//ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

And then implement:

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

}
- (void)keyboardWillHide:(NSNotification *)notification {

}
沫尐诺 2024-10-28 04:50:10

我的代码。也许有人会有用:
tableView

.m中的自定义文本字段单元格

    @property (nonatomic, strong) UITextField *currentCellTextField;

       CustomCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
            if (cell == nil) {
                NSArray * nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
                cell = (CustomCell *)[nib objectAtIndex:0];
                cell.textfield.delegate = self;
            }
      - (void) textFieldDidBeginEditing:(UITextField *)textField
 {
  self.currentCellTextField = textField;

  CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField];
  NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt];

if (path.section >= 2) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    self.organisationTableView.contentInset = UIEdgeInsetsMake(0, 0, kOFFSET_FOR_KEYBOARD, 0);
    CGPoint siize = self.organisationTableView.contentOffset;
    siize.y =(pnt.y-170);
    self.organisationTableView.contentOffset = CGPointMake(0, siize.y);
    [UIView commitAnimations];
    }
 }

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

CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField];
NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt];

 if (path.section >= 2) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    self.organisationTableView.contentInset = UIEdgeInsetsZero;
    self.organisationTableView.contentOffset = CGPointMake(0, self.organisationTableView.contentOffset.y);
    [UIView commitAnimations];
      }

 return YES;
   }

My code. Maybe someone will be useful:
Custom textField cell in tableView

.m

    @property (nonatomic, strong) UITextField *currentCellTextField;

       CustomCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
            if (cell == nil) {
                NSArray * nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
                cell = (CustomCell *)[nib objectAtIndex:0];
                cell.textfield.delegate = self;
            }
      - (void) textFieldDidBeginEditing:(UITextField *)textField
 {
  self.currentCellTextField = textField;

  CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField];
  NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt];

if (path.section >= 2) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    self.organisationTableView.contentInset = UIEdgeInsetsMake(0, 0, kOFFSET_FOR_KEYBOARD, 0);
    CGPoint siize = self.organisationTableView.contentOffset;
    siize.y =(pnt.y-170);
    self.organisationTableView.contentOffset = CGPointMake(0, siize.y);
    [UIView commitAnimations];
    }
 }

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

CGPoint pnt = [self.organisationTableView convertPoint:textField.bounds.origin fromView:textField];
NSIndexPath* path = [self.organisationTableView indexPathForRowAtPoint:pnt];

 if (path.section >= 2) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    self.organisationTableView.contentInset = UIEdgeInsetsZero;
    self.organisationTableView.contentOffset = CGPointMake(0, self.organisationTableView.contentOffset.y);
    [UIView commitAnimations];
      }

 return YES;
   }
一绘本一梦想 2024-10-28 04:50:10

就我而言,我的 UITableview 位于另一个 UIView 中,而 UIvie 位于主 UIScrollview 中。所以我对这类问题使用了更通用的解决方案。
我只是在特定的 UIScrollView 中找到了单元格的 Y 坐标,然后滚动到正确的点:

-(void)textFieldDidBeginEditing:(UITextField *)textField{
float kbHeight = 216;//Hard Coded and will not support lanscape mode
UITableViewCell *cell = (UITableViewCell *)[textField superview];
float scrollToHeight = [self FindCordinate:cell];
[(UIScrollView *)self.view setContentOffset:CGPointMake(0, scrollToHeight - kbHeight + cell.frame.size.height) animated:YES];
}

-(float)FindCordinate:(UIView *)cell{
float Ycordinate = 0.0;
while ([cell superview] != self.view) {
    Ycordinate += cell.frame.origin.y;
    cell = [cell superview];
}
Ycordinate += cell.frame.origin.y;
return Ycordinate;
}

In my case my UITableview was inside another UIView and that UIvie was in the main UIScrollview. So I used more general solution for those kind of problems.
I simply found the Y coordinate of my cell in the specific UIScrollView and then scrolled to correct point:

-(void)textFieldDidBeginEditing:(UITextField *)textField{
float kbHeight = 216;//Hard Coded and will not support lanscape mode
UITableViewCell *cell = (UITableViewCell *)[textField superview];
float scrollToHeight = [self FindCordinate:cell];
[(UIScrollView *)self.view setContentOffset:CGPointMake(0, scrollToHeight - kbHeight + cell.frame.size.height) animated:YES];
}

-(float)FindCordinate:(UIView *)cell{
float Ycordinate = 0.0;
while ([cell superview] != self.view) {
    Ycordinate += cell.frame.origin.y;
    cell = [cell superview];
}
Ycordinate += cell.frame.origin.y;
return Ycordinate;
}
被你宠の有点坏 2024-10-28 04:50:10

另一个简单的解决方案是为最后一个表格部分的页脚添加额外的空间:

- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    if (section == lastSection) {
        return keyboard height;
    }
    return 0;
}

我们也可以将图标添加到该区域。 :)

Another simple solution is adding an additional space for the footer of the last table section:

- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    if (section == lastSection) {
        return keyboard height;
    }
    return 0;
}

We can add our icon into this area as well. :)

东北女汉子 2024-10-28 04:50:10

您可以尝试将 UITableViewController 添加到 UIViewController 而不仅仅是表视图。这样你就可以调用 UITableViewController 的 viewWillAppear 并且一切都会正常工作。

例子:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [tableViewController viewWillAppear:animated];
}

You can try adding a UITableViewController to the UIViewController instead of just a table view. This way you can call UITableViewController's viewWillAppear and everything will appear to work.

Example:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [tableViewController viewWillAppear:animated];
}
无法回应 2024-10-28 04:50:10

我在 @FunkyKat 和 @bmauter 答案中添加了一个小功能(顺便说一句,这是一个很好的答案,它应该是被接受的)

在键盘幻影之前/之后,保留了常规的表视图边缘插入。

- (void)keyboardWillShow:(NSNotification *)sender
{
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = self.tableView.contentInset;
        edgeInsets.bottom += height;
        self.tableView.contentInset = edgeInsets;
        edgeInsets = self.tableView.scrollIndicatorInsets;
        edgeInsets.bottom += height;
        self.tableView.scrollIndicatorInsets = edgeInsets;
    }];
}

- (void)keyboardWillHide:(NSNotification *)sender
{
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = self.tableView.contentInset;
        edgeInsets.bottom -= height;
        self.tableView.contentInset = edgeInsets;
        edgeInsets = self.tableView.scrollIndicatorInsets;
        edgeInsets.bottom -= height;
        self.tableView.scrollIndicatorInsets = edgeInsets;
    }];
}

I have add a little feature to @FunkyKat and @bmauter answers (great answer by the way, it should be the one accepted)

The regular Table View edge insets is preserved, before/after the keyboard apparition.

- (void)keyboardWillShow:(NSNotification *)sender
{
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = self.tableView.contentInset;
        edgeInsets.bottom += height;
        self.tableView.contentInset = edgeInsets;
        edgeInsets = self.tableView.scrollIndicatorInsets;
        edgeInsets.bottom += height;
        self.tableView.scrollIndicatorInsets = edgeInsets;
    }];
}

- (void)keyboardWillHide:(NSNotification *)sender
{
    CGSize kbSize = [[[sender userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    NSTimeInterval duration = [[[sender userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGFloat height = UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]) ? kbSize.width : kbSize.height;

    [UIView animateWithDuration:duration animations:^{
        UIEdgeInsets edgeInsets = self.tableView.contentInset;
        edgeInsets.bottom -= height;
        self.tableView.contentInset = edgeInsets;
        edgeInsets = self.tableView.scrollIndicatorInsets;
        edgeInsets.bottom -= height;
        self.tableView.scrollIndicatorInsets = edgeInsets;
    }];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文