256

試行錯誤の末、諦めて質問させていただきました。同様の問題を抱えている人をたくさん見てきましたが、すべての答えを正しく機能させることはできません。

UITableViewカスタムセルで構成されたがあります。セルは、隣り合った 5 つのテキスト フィールドで構成されています (グリッドのようなもの)。

の下部にあるセルをスクロールして編集しようとすると、セルをUITableViewキーボードの上に適切に配置することができません。

ビューサイズの変更などについて話している多くの回答を見てきましたが、これまでのところうまく機能していません。

具体的なコード例でこれを行う「正しい」方法を誰かが明確にすることはできますか?

4

45 に答える 45

128

UIViewController の代わりに UITableViewController を使用すると、自動的に実行されます。

于 2010-09-21T03:42:12.937 に答える
94

スクロールを行う関数は、はるかに単純になる可能性があります。

- (void) textFieldDidBeginEditing:(UITextField *)textField {
    UITableViewCell *cell;

    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
    // Load resources for iOS 6.1 or earlier
        cell = (UITableViewCell *) textField.superview.superview;

    } else {
        // Load resources for iOS 7 or later
        cell = (UITableViewCell *) textField.superview.superview.superview; 
       // TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!
    }
    [tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

それでおしまい。まったく計算なし。

于 2009-04-15T12:21:53.927 に答える
71

私は非常に似たようなことをしていますが、それは一般的であり、コードに固有のものを計算する必要はありません。コードのコメントを確認してください。

MyUIViewController.h 内

@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
     UITableView *myTableView;
     UITextField *actifText;
}

@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;

-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;

@end

MyUIViewController.m 内

@implementation MyUIViewController

@synthesize myTableView;
@synthesize actifText;

- (void)viewDidLoad 
{
    // Register notification when the keyboard will be show
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillShow:)
                                          name:UIKeyboardWillShowNotification
                                          object:nil];

    // Register notification when the keyboard will be hide
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillHide:)
                                          name:UIKeyboardWillHideNotification
                                          object:nil];
}

// To be link with your TextField event "Editing Did Begin"
//  memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.actifText = textField;
}

// To be link with your TextField event "Editing Did End"
//  release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.actifText = nil;
}

-(void) keyboardWillShow:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    // Start animation
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Reduce size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height -= keyboardBounds.size.height;
    else 
        frame.size.height -= keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    // Scroll the table view to see the TextField just above the keyboard
    if (self.actifText)
      {
        CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
        [self.myTableView scrollRectToVisible:textFieldRect animated:NO];
      }

    [UIView commitAnimations];
}

-(void) keyboardWillHide:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Increase size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height += keyboardBounds.size.height;
    else 
        frame.size.height += keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    [UIView commitAnimations];
}

@end

Swift 1.2+ バージョン:

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var activeText: UITextField!
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillShow:"),
            name: UIKeyboardWillShowNotification,
            object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillHide:"),
            name: UIKeyboardWillHideNotification,
            object: nil)
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        activeText = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        activeText = nil
    }

    func keyboardWillShow(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height -= keyboardSize.height
            tableView.frame = frame
            if activeText != nil {
                let rect = tableView.convertRect(activeText.bounds, fromView: activeText)
                tableView.scrollRectToVisible(rect, animated: false)
            }
            UIView.commitAnimations()
        }
    }

    func keyboardWillHide(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height += keyboardSize.height
            tableView.frame = frame
            UIView.commitAnimations()
        }
    }
}
于 2010-04-13T14:46:50.160 に答える
49

Bartłomiej Semańczyk ソリューションに基づくSwift 3の最も単純なソリューション:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

// MARK: Keyboard Notifications

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2, animations: {
        // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    })
}
于 2016-12-08T13:26:15.337 に答える
45

同じ問題がありましたが、1 つのビューにしか表示されないことに気付きました。そこで、コントローラーの違いを探し始めました。

- (void)viewWillAppear:(BOOL)animatedスクロール動作がスーパーインスタンスに設定されていることがわかりました。

したがって、必ず次のように実装してください。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // your code
}

UIViewControllerまたはUITableViewController;を使用するかどうかは問題ではありません。UITableViewをself.viewのサブビューとして入れてチェックしましたUIViewController。同じ動作でした。[super viewWillAppear:animated];呼び出しが欠落している場合、ビューはスクロールできませんでした。

于 2011-05-29T00:42:21.937 に答える
41

ここの投稿全体を読んでいなかったので、これを見逃したかもしれませんが、思いついたのは一見単純に思えます。私はこれをすべての状況でテストして絞り器に通していませんが、問題なく動作するはずです。

tableview の contentInset をキーボードの高さに合わせて調整し、セルを一番下までスクロールします。

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

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    self.myTableView.contentInset = contentInsets;
    self.myTableView.scrollIndicatorInsets = contentInsets;

    [self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

そしてもちろん

- (void)keyboardWasHidden:(NSNotification *)aNotification
{
    [UIView animateWithDuration:.3 animations:^(void) 
    {
        self.myTableView.contentInset = UIEdgeInsetsZero;
        self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
    }];
}

これは単純すぎますか?私は何かを逃していますか?これまでのところ、問題なく機能していますが、私が言ったように、絞り器に通していません...

于 2012-08-18T00:12:58.713 に答える
35

Appleのアプリの動作に合わせた解決策を思いついたと思います。

まず、viewWillAppearで:キーボード通知をサブスクライブします。これにより、キーボードがいつ表示および非表示になるかがわかり、システムがキーボードのサイズを通知しますが、viewWillDisappear:で登録を解除することを忘れないでください。

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

以下のようなメソッドを実装して、キーボードが表示されたら表示領域に一致するようにtableViewのサイズを調整します。ここでは、キーボードの状態を個別に追跡しているので、フィールドが変更されるたびにこれらの通知を受け取るので、tableViewをフルハイトに戻すタイミングを自分で選択できます。KeyboardWillHide:を実装することを忘れないでください。そして、tableViewのサイズを修正するために適切な場所を選択してください。

-(void) keyboardWillShow:(NSNotification *)note
{
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
    keyboardHeight = keyboardBounds.size.height;
    if (keyboardIsShowing == NO)
    {
        keyboardIsShowing = YES;
        CGRect frame = self.view.frame;
        frame.size.height -= keyboardHeight;

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:0.3f];
        self.view.frame = frame;
        [UIView commitAnimations];
    }
}

これがスクロールビットです。最初にいくつかのサイズを計算してから、表示領域のどこにいるかを確認し、スクロールする四角形をテキストフィールドの中央より上または下のハーフビューに設定します。ビューのどこにあるか。この場合、UITextFieldsの配列とそれらを追跡する列挙型があるため、rowHeightに行番号を掛けると、この外部ビュー内のフレームの実際のオフセットが得られます。

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect frame = textField.frame;
    CGFloat rowHeight = self.tableView.rowHeight;
    if (textField == textFields[CELL_FIELD_ONE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_ONE;
    }
    else if (textField == textFields[CELL_FIELD_TWO])
    {
        frame.origin.y += rowHeight * CELL_FIELD_TWO;
    }
    else if (textField == textFields[CELL_FIELD_THREE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_THREE;
    }
    else if (textField == textFields[CELL_FIELD_FOUR])
    {
        frame.origin.y += rowHeight * CELL_FIELD_FOUR;
    }
    CGFloat viewHeight = self.tableView.frame.size.height;
    CGFloat halfHeight = viewHeight / 2;
    CGFloat midpoint = frame.origin.y + (textField.frame.size.height / 2);
    if (midpoint < halfHeight)
    {
        frame.origin.y = 0;
        frame.size.height = midpoint;
    }
    else
    {
        frame.origin.y = midpoint;
        frame.size.height = midpoint;
    }
    [self.tableView scrollRectToVisible:frame animated:YES];
}

これは非常にうまく機能しているようです。

于 2009-03-23T01:49:32.950 に答える
35

を使用できる場合はUITableViewController、無料で機能を利用できます。ただし、これがオプションでない場合もあります。特に、UITableView.

ここで紹介するソリューションの中には、iOS 4 以降では機能しないもの、iPad または横向きモードでは機能しないもの、Bluetooth キーボード (スクロールが必要ない) では機能しないもの、機能しないものがあります。複数のテキストフィールドを切り替えるときに機能します。したがって、いずれかのソリューションを選択する場合は、必ずこれらのケースをテストしてください。これは、 InAppSettingsKit で使用するソリューション です:

- (void)_keyboardWillShow:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
        NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
        if (!keyboardFrameValue) {
            keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
        }

        // Reduce the tableView height by the part of the keyboard that actually covers the tableView
        CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            windowRect = IASKCGRectSwap(windowRect);
        }
        CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
        }
        CGRect frame = _tableView.frame;
        frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = frame;
        [UIView commitAnimations];

        UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
        NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];

        // iOS 3 sends hide and show notifications right after each other
        // when switching between textFields, so cancel -scrollToOldPosition requests
        [NSObject cancelPreviousPerformRequestsWithTarget:self];

        [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }
}

- (void) scrollToOldPosition {
  [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)_keyboardWillHide:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = self.view.bounds;
        [UIView commitAnimations];

        [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
    }
}   

InAppSettingsKitのクラスの完全なコードを次に示します。テストするには、上記のシナリオをテストできる「完全なリスト」子ペインを使用します。

于 2010-12-13T16:01:09.117 に答える
8

皆さんがこれらすべてを読んで解決策をすでに得ていることを願っています。しかし、私は次のように私の解決策を見つけました。のセルが既にあることを期待していますUITextField。そのため、準備として、行インデックスをテキスト フィールドのタグに保持します。

cell.textField.tag = IndexPath.row;

以下のように、グローバル スコープactiveTextFieldで のインスタンスを作成します。UITextField

@interface EditViewController (){

    UITextField *activeTextField;

}

したがって、最後に私のコードをコピーして貼り付けてください。また、追加することを忘れないでくださいUITextFieldDelegate

#pragma mark - TextField Delegation

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

    activeTextField = textField;

    return YES;
}

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

    activeTextField = nil;

}

キーボードを登録しますnotifications

#pragma mark - Keyboard Activity

- (void)registerForKeyboardNotifications

{

    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWasShown:)

                                             name:UIKeyboardDidShowNotification object:nil];



    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWillBeHidden:)

                                             name:UIKeyboardWillHideNotification object:nil];



}

ハンドル キーボードNotifications:

UIKeyboardDidShowNotificationが送信されたときに呼び出されます。

- (void)keyboardWasShown:(NSNotification*)aNotification

{

    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

    NSIndexPath *currentRowIndex = [NSIndexPath indexPathForRow:activeTextField.tag inSection:0];

    [self.tableView scrollToRowAtIndexPath:currentRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];

}

UIKeyboardWillHideNotificationが送信されたときに呼び出されます

- (void)keyboardWillBeHidden:(NSNotification*)aNotification

{

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

}

1 つ残っているのは、次のようregisterForKeyboardNotificationsにメソッド内でメソッドを呼び出すことです。ViewDidLoad

- (void)viewDidLoad {

    [super viewDidLoad];

    // Registering keyboard notification

    [self registerForKeyboardNotifications];

    // Your codes here...

}

あなたのtextFields意志がキーボードに隠されていないことを願っています。

于 2015-01-03T21:36:19.157 に答える
6

いくつかの回答 (特に Ortwin Gentz、ユーザー 98013) と別の投稿からの空白を組み合わせて埋めると、縦向きまたは横向きモードの iPad で SDK 4.3 をすぐに使用できます。

@implementation UIView (FindFirstResponder)
- (UIResponder *)findFirstResponder
{
  if (self.isFirstResponder) {        
    return self;     
  }

  for (UIView *subView in self.subviews) {
    UIResponder *firstResponder = [subView findFirstResponder];
    if (firstResponder != nil) {
      return firstResponder;
    }
  }

  return nil;
}
@end

@implementation MyViewController

- (UIResponder *)currentFirstResponder {
  return [self.view findFirstResponder];
}

- (IBAction)editingEnded:sender {
  [sender resignFirstResponder];
}

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

- (void)textFieldDidBeginEditing:(UITextField *)textField {
  UITableViewCell *cell = (UITableViewCell*) [[textField superview] superview];
  [_tableView scrollToRowAtIndexPath:[_tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)keyboardWillShow:(NSNotification*)notification {
  if ([self currentFirstResponder] != nil) {
    NSDictionary* userInfo = [notification userInfo];

    // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
    NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
    if (!keyboardFrameValue) {
      keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
    }

    // Reduce the tableView height by the part of the keyboard that actually covers the tableView
    CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
    CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
    CGRect frame = _tableView.frame;
    if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
      windowRect = CGRectMake(windowRect.origin.y, windowRect.origin.x, windowRect.size.height, windowRect.size.width);
      viewRectAbsolute = CGRectMake(viewRectAbsolute.origin.y, viewRectAbsolute.origin.x, viewRectAbsolute.size.height, viewRectAbsolute.size.width);
    }
    frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    _tableView.frame = frame;
    [UIView commitAnimations];

    UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
    NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];

    // iOS 3 sends hide and show notifications right after each other
    // when switching between textFields, so cancel -scrollToOldPosition requests
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    _topmostRowBeforeKeyboardWasShown = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
    [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  }
}

- (void) scrollToOldPosition {
  [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)keyboardWillHide:(NSNotification*)notification {
  if ([self currentFirstResponder] != nil) {

    NSDictionary* userInfo = [notification userInfo];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    _tableView.frame = self.view.bounds;
    [UIView commitAnimations];

    [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
  }
}   

@end
于 2011-08-03T02:35:10.497 に答える
5

私のアプローチ:

最初に UITextField をサブクラス化し、indexPath プロパティを追加します。cellFor... メソッドで、indexPath プロパティを渡します。

次に、次のコードを追加します。

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:textField.indexPath];

CGPoint cellPoint = [cell convertPoint:textField.center toView:self.tableView];
[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, cellPoint.y-50);}];

textFieldShould/WillBegin...などに。

キーボードが消えたら、次のように元に戻す必要があります。

[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, 0);}];
于 2012-09-29T12:03:22.073 に答える
5

uitableview を使用してテキストフィールドを配置する場合 ( Jeff Lamarche から)、デリゲート メソッドを使用してテーブルビューをスクロールするだけです。

(注:私のテキストフィールドは、テーブルビューの行と同じインデックスを持つ配列に保存されています)

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

        int index;
        for(UITextField *aField in textFields){

            if (textField == aField){
                index = [textFields indexOfObject:aField]-1;
            }
        }

         if(index >= 0) 
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];

        [super textFieldDidBeginEditing:textField];
    }
于 2009-05-01T06:09:39.630 に答える
5

を使用する場合Three20は、autoresizesForKeyboardプロパティを使用します。ビューコントローラーの-initWithNibName:bundleメソッドに設定するだけです

self.autoresizesForKeyboard = YES

これにより、次の処理が行われます。

  1. キーボード通知をリッスンし、テーブル ビューのフレームを調整する
  2. ファーストレスポンダまでスクロール

やった、やった。

于 2010-09-21T13:19:02.407 に答える
5

キーボード通知は機能しますが、そのための Apple のサンプル コードは、スクロール ビューがウィンドウのルート ビューであることを前提としています。通常はそうではありません。正しいオフセットを得るには、タブバーなどを補正する必要があります。

思ったより簡単です。UITableViewController で使用するコードを次に示します。これには、hiddenRect と keyboardShown の 2 つのインスタンス変数があります。

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
    if (keyboardShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    // Get the frame of the keyboard.
    NSValue *centerValue = [info objectForKey:UIKeyboardCenterEndUserInfoKey];
    NSValue *boundsValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    CGPoint keyboardCenter = [centerValue CGPointValue];
    CGRect keyboardBounds = [boundsValue CGRectValue];
    CGPoint keyboardOrigin = CGPointMake(keyboardCenter.x - keyboardBounds.size.width / 2.0,
                                         keyboardCenter.y - keyboardBounds.size.height / 2.0);
    CGRect keyboardScreenFrame = { keyboardOrigin, keyboardBounds.size };


    // Resize the scroll view.
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = scrollView.frame;
    CGRect keyboardFrame = [scrollView.superview convertRect:keyboardScreenFrame fromView:nil];
    hiddenRect = CGRectIntersection(viewFrame, keyboardFrame);

    CGRect remainder, slice;
    CGRectDivide(viewFrame, &slice, &remainder, CGRectGetHeight(hiddenRect), CGRectMaxYEdge);
    scrollView.frame = remainder;

    // Scroll the active text field into view.
    CGRect textFieldRect = [/* selected cell */ frame];
    [scrollView scrollRectToVisible:textFieldRect animated:YES];

    keyboardShown = YES;
}


// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
    // Reset the height of the scroll view to its original value
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = [scrollView frame];
    scrollView.frame = CGRectUnion(viewFrame, hiddenRect);

    keyboardShown = NO;
}
于 2009-07-11T22:01:52.093 に答える
4

より合理化されたソリューション。UITextFieldデリゲートメソッドに組み込まれるため、UIKeyboard通知をいじる必要はありません。

実装上の注意:

kSettingsRowHeight -- UITableViewCell の高さ。

offsetTarget と offsetThreshold は、kSettingsRowHeight から取得されます。別の行の高さを使用する場合は、それらの値をポイントの y プロパティに設定します。[alt: 別の方法で行オフセットを計算します。]

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
CGFloat offsetTarget    = 113.0f; // 3rd row
CGFloat offsetThreshold = 248.0f; // 6th row (i.e. 2nd-to-last row)

CGPoint point = [self.tableView convertPoint:CGPointZero fromView:textField];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
if (point.y > offsetThreshold) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y + kSettingsRowHeight,
                      frame.size.width,
                      frame.size.height);
} else if (point.y > offsetTarget) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y,
                      frame.size.width,
                      frame.size.height);
} else {
    self.tableView.frame = CGRectMake(0.0f,
                      0.0f,
                      frame.size.width,
                      frame.size.height);
}

[UIView commitAnimations];

return YES;

}

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

[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
self.tableView.frame = CGRectMake(0.0f,
                  0.0f,
                  frame.size.width,
                  frame.size.height);

[UIView commitAnimations];

return YES;

}

于 2009-08-04T07:18:34.460 に答える
3

テーブルにテキストフィールドがあるため、実際にはテーブルのサイズを変更するのが最善の方法です.tableView.frameの高さをキーボードのサイズ分小さくする必要があります(約165ピクセルだと思います)。キーボードが閉じられます。

ユーザーがスクロールしたくない場合は、必要に応じて、その時点で tableView のユーザー操作を無効にすることもできます。

于 2009-02-28T18:37:06.343 に答える
2

GoogleとStackOverflowで見つかった大量のソリューションを紹介した後、私はこのような問題を自分で解決しました。

まず、UIScrollViewのIBOutletが設定されていることを確認してから、Apple Doc:KeyboardManagementをよく見てください。最後に、背景をスクロールできるが、キーボードがテキストフィールドをカバーしている場合は、次のコードを参照してください。

// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;

if (aRect.size.height < activeField.frame.origin.y+activeField.frame.size.height) {

    CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y+activeField.frame.size.height-aRect.size.height);

    [scrollView setContentOffset:scrollPoint animated:YES];

この作品とAppleの作品の主な違いは、if条件にあります。Appleのスクロール距離の計算と、キーボードでカバーされているテキストフィールドが正確でないかどうかの条件を信じているので、上記のように変更しました。

それが機能するかどうか教えてください

于 2012-08-18T10:10:47.940 に答える
2

This works perfectly, and on iPad too.

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

    if(textField == textfield1){
            [accountName1TextField becomeFirstResponder];
        }else if(textField == textfield2){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield3 becomeFirstResponder];

        }else if(textField == textfield3){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield4 becomeFirstResponder];

        }else if(textField == textfield4){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield5 becomeFirstResponder];

        }else if(textField == textfield5){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield6 becomeFirstResponder];

        }else if(textField == textfield6){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:4 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield7 becomeFirstResponder];

        }else if(textField == textfield7){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield8 becomeFirstResponder];

        }else if(textField == textfield8){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield9 becomeFirstResponder];

        }else if(textField == textfield9){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textField resignFirstResponder];
        }
于 2010-10-23T07:11:24.583 に答える
2

非常に興味深いディスカッション スレッドです。私も同じ問題に直面しました。

  1. カスタムセルを使用していて、テキストフィールドがその中にありました。
  2. 要件を満たすために UIViewController を使用する必要があったため、UITableViewController を利用できませんでした。
  3. テーブルセルにフィルター/ソート基準がありました。つまり、セルが変化し続け、インデックスパスを追跡し続け、すべてが役に立ちません。

ここのスレッドを読んで、私のバージョンを実装しました。これは、iPad のコンテンツを横向きモードで押し上げるのに役立ちました。これがコードです(これは完全ではありませんが、私の問題を修正しました)最初にカスタムセルクラスにデリゲートが必要です。編集が始まると、テキストフィールドがビューコントローラーに送信され、そこにactivefield = theTextFieldが設定されます

// ランドスケープ モードのみを処理するために実装

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect aRect = myTable.frame;

    CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);

    aRect.size.height -= kbSize.height+50;
// This will the exact rect in which your textfield is present
        CGRect rect =  [myTable convertRect:activeField.bounds fromView:activeField];
// Scroll up only if required
    if (!CGRectContainsPoint(aRect, rect.origin) ) {


            [myTable setContentOffset:CGPointMake(0.0, rect.origin.y) animated:YES];

    }


}

// UIKeyboardWillHideNotification が送信されたときに呼び出されます

- (void)keyboardWillHide:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    myTable.contentInset = contentInsets;
    myTable.scrollIndicatorInsets = contentInsets;
    NSDictionary* info = [aNotification userInfo];
    CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);
    CGRect bkgndRect = activeField.superview.frame;
    bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [myTable setContentOffset:CGPointMake(0.0, 10.0) animated:YES];
}

-anoop4real

于 2012-07-17T17:11:11.283 に答える
2

このソリューションは私にとってはうまくいきます。行に注意してください

[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];

160 の値を変更して、それに合わせて作業することができます

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
                        bkgndRect.size.height += kbSize.height;
     [activeField.superview setFrame:bkgndRect];
     [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   activeField = textField;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
 {
     activeField = nil;
 }
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    tableView.contentInset = contentInsets;
    tableView.scrollIndicatorInsets = contentInsets;
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
    //bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}
于 2011-12-02T18:28:05.387 に答える
2

したがって、これらの現在のソリューションを使用しようとする (そして完全に失敗する) 何時間もの厳しい作業の後、ようやくうまく機能するようになり、新しいアニメーション ブロックを使用するように更新しました。私の答えは、上記の Ortwin の答えに完全に基づいています。

したがって、何らかの理由で上記のコードが機能しませんでした。私のセットアップは他のセットアップとかなり似ているように見えましたが、iPad または 4.3 を使用していたためか、わかりません。風変わりな計算を行っていて、テーブルビューが画面から消えていました。

私のソリューションの最終結果を参照してください: http://screencast.com/t/hjBCuRrPC (写真は無視してください。:-P)

そこで、Ortwin が行っていたことの要点を理解しましたが、テーブル ビューの origin.y と size.height をキーボードの高さと合計するために、計算方法を変更しました。その結果からウィンドウの高さを差し引くと、交差点がどれだけあるかがわかります。0 より大きい場合 (オーバーラップがある場合)、フレームの高さのアニメーションを実行します。

さらに、1) アニメーションが完了するまでセルにスクロールするのを待つこと、および 2) キーボードを非表示にするときに UIViewAnimationOptionBeginFromCurrentState オプションを使用することによって解決された再描画の問題がいくつかありました。

注意すべき点がいくつかあります。

  • _topmostRowBeforeKeyboardWasShown と _originalFrame は、ヘッダーで宣言されたインスタンス変数です。
  • self.guestEntryTableView は私の tableView です (私は外部ファイルにいます)
  • IASKCGRectSwap は、フレームの座標を反転するための Ortwin の方法です。
  • 少なくとも50pxが表示される場合にのみ、tableViewの高さを更新します
  • 私はUIViewControllerにいないので、self.viewを持っていないので、tableViewを元のフレームに戻すだけです

繰り返しますが、私 Ortwin がその要点を提供しなければ、私はこの答えに近づくことはできなかったでしょう。コードは次のとおりです。

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.activeTextField = textField;

    if ([self.guestEntryTableView indexPathsForVisibleRows].count) {
        _topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[self.guestEntryTableView indexPathsForVisibleRows] objectAtIndex:0];
    } else {
        // this should never happen
        _topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0];
        [textField resignFirstResponder];
    }
}

- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.activeTextField = nil;
}

- (void)keyboardWillShow:(NSNotification*)notification {
    NSDictionary* userInfo = [notification userInfo];

    NSValue* keyboardFrameValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

    // Reduce the tableView height by the part of the keyboard that actually covers the tableView
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
    CGRect viewRectAbsolute = [self.guestEntryTableView convertRect:self.guestEntryTableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
    CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
    if (UIInterfaceOrientationLandscapeLeft == orientation ||UIInterfaceOrientationLandscapeRight == orientation ) {
        windowRect = IASKCGRectSwap(windowRect);
        viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
        keyboardFrame = IASKCGRectSwap(keyboardFrame);
    }

    // fix the coordinates of our rect to have a top left origin 0,0
    viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation, windowRect.size.width, windowRect.size.height);

    CGRect frame = self.guestEntryTableView.frame;
    _originalFrame = self.guestEntryTableView.frame;

    int remainder = (viewRectAbsolute.origin.y + viewRectAbsolute.size.height + keyboardFrame.size.height) - windowRect.size.height;

    if (remainder > 0 && !(remainder > frame.size.height + 50)) {
        frame.size.height = frame.size.height - remainder;
        float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        [UIView animateWithDuration: duration
                        animations:^{
                            self.guestEntryTableView.frame = frame;
                        }
                        completion:^(BOOL finished){
                            UITableViewCell *textFieldCell = (UITableViewCell*) [[self.activeTextField superview] superview];
                            NSIndexPath *textFieldIndexPath = [self.guestEntryTableView indexPathForCell:textFieldCell];
                            [self.guestEntryTableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
                        }];
    }

}

- (void)keyboardWillHide:(NSNotification*)notification {
    NSDictionary* userInfo = [notification userInfo];
    float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration: duration
                          delay: 0.0
                        options: (UIViewAnimationOptionBeginFromCurrentState)
                     animations:^{
                         self.guestEntryTableView.frame = _originalFrame;
                     }
                     completion:^(BOOL finished){
                         [self.guestEntryTableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
                     }];

}   

#pragma mark CGRect Utility function
CGRect IASKCGRectSwap(CGRect rect) {
    CGRect newRect;
    newRect.origin.x = rect.origin.y;
    newRect.origin.y = rect.origin.x;
    newRect.size.width = rect.size.height;
    newRect.size.height = rect.size.width;
    return newRect;
}

CGRect FixOriginRotation(CGRect rect, UIInterfaceOrientation orientation, int parentWidth, int parentHeight) {
    CGRect newRect;
    switch(orientation)
    {
        case UIInterfaceOrientationLandscapeLeft:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), rect.origin.y, rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            newRect = CGRectMake(rect.origin.x, parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationPortrait:
            newRect = rect;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
    }
    return newRect;
}
于 2011-07-18T08:45:17.227 に答える
2

私はほぼ同じアプローチを試み、同じためのよりシンプルで小さなコードを思いつきました。IBOutlet iTextView を作成し、IB で UITextView に関連付けました。

 -(void)keyboardWillShow:(NSNotification *)notification
    {
        NSLog(@"Keyboard");
        CGRect keyFrame = [[[notification userInfo]objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];

        [UIView beginAnimations:@"resize view" context:nil];
        [UIView setAnimationCurve:1];
        [UIView setAnimationDuration:1.0];
        CGRect frame = iTableView.frame;
        frame.size.height = frame.size.height -  keyFrame.size.height;
        iTableView.frame = frame;
        [iTableView scrollRectToVisible:frame animated:YES];
        [UIView commitAnimations];

    }
于 2011-05-13T05:00:24.820 に答える
2

Swiftで UITableViewCell の UITextField の Get indexPathからのテキスト フィールドの正確なポイントを使用する Swift の例 :

func textFieldDidBeginEditing(textField: UITextField) {
    let pointInTable = textField.convertPoint(textField.bounds.origin, toView: self.accountsTableView)
    let textFieldIndexPath = self.accountsTableView.indexPathForRowAtPoint(pointInTable)
    accountsTableView.scrollToRowAtIndexPath(textFieldIndexPath!, atScrollPosition: .Top, animated: true)
}
于 2015-05-21T06:34:55.153 に答える
1

私は自分のソリューション (または QuickDialog のソリューション) を帽子に投げ込みます。基本的にスクロールに合わせてアニメーションするのを待ちます。マジックナンバーの代わりにキーボードアニメーションのJITを取得できるといいですね。

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (textField == self.emailTextField) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 50 * USEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
        });
    }
}
于 2014-01-28T18:05:48.703 に答える
1

表示中

-(void)viewdidload{

[super viewdidload];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
}

    -(void)keyboardWillChange:(NSNotification*)sender{

        NSLog(@"keyboardwillchange sender %@",sender);

float margin=0  // set your own topmargin


        CGFloat originY = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;


        if (originY >= self.view.frame.size.height){

            NSLog(@"keyboardclose");



            [tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, self.view.frame.size.height-margin)];

        }else{

            NSLog(@"keyobard on");

            float adjustedHeight = self.view.frame.size.height - margin - (self.view.frame.size.height-originY);

            [tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, adjustedHeight)];
        }







    }
于 2016-02-12T09:14:38.850 に答える
1

私は自分のプロジェクトでこれをよく使用します。このソリューションは、スクロールビュー、テーブルビュー、またはコレクションビューで機能し、セットアップが簡単です。また、キーボードの「次へ」ボタンを自動的にフックして、テキスト フィールドを切り替えます。

ここで確認してください

于 2014-02-12T20:27:14.897 に答える
1

別の簡単な方法 (1 つのセクションでのみ機能)

//cellForRowAtIndexPath
UItextField *tf;
[cell addSubview:tf];
tf.tag = indexPath.row;
tf.delegate = self;

//textFieldDidBeginEditing:(UITextField *)text
[[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES];
于 2011-11-23T16:25:17.613 に答える
1

これは、Sam Ho と Marcel W の回答と、私のくだらないコードに加えられた私自身のバグ修正の混合物です。UITableViewController を使用していました。キーボードが表示されているときにテーブルのサイズが正しく変更されるようになりました。

1)viewDidLoad私は追加しました:

self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

2)とのsuper等価物を呼び出すのを忘れていました。これらを再度追加しました。viewWillAppearawakeFromNib

于 2012-07-26T17:18:59.440 に答える
1

UITableView が UITableView ではなく UITableViewController のサブクラスによって管理され、テキスト フィールド デリゲートが UITableViewController である場合、すべてのスクロールを自動的に管理する必要があります。これらの他のすべてのコメントを実際に実装するのは非常に困難です。

良い例については、Apple のサンプル コード プロジェクト: TaggedLocations を参照してください。

自動的にスクロールすることがわかりますが、これを行うコードはないようです。このプロジェクトにはカスタム テーブル ビュー セルも含まれているため、それをガイドとしてアプリケーションを構築すると、目的の結果が得られるはずです。

于 2012-03-05T06:09:43.257 に答える
1

私はこれらを使用していますが、それらは魅力的に機能します:

BSKeyboardControls - BSKeyboardControls github

TPKeyboardAvoiding - TPKeyboardAvoiding github

于 2014-02-13T08:30:43.407 に答える
1

UITableViewController確かに、スクロールは自動的に行われます。を使用する場合との違いは、 を使用する場合、 をUIViewController使用してプログラムで Navbar-Buttonitems を作成する必要があることです。NavigationControllerTableViewController

于 2011-03-20T19:59:48.097 に答える
0

iOS 5.0のlibリファレンスをもう一度調べたところ、「キーボードの下にあるコンテンツの移動」というタイトルのこのセクションが見つかりました:TextAndWebiPhoneOS KeyboardManagement

これはiOS5以降の新しいものですか?私は何か他のことの真っ只中にいるので、まだそれを読んでいませんが、おそらく他の人がもっと知っていて、ここで私や他の人を啓発することができます。

Appleのドキュメントはここで説明されている内容に取って代わりますか、それともここの情報はiOS 5 SDKユーザーにとってまだ有用ですか?

于 2011-10-26T11:07:03.600 に答える
0

これを行う「正しい」方法はないと思います。ユースケースに最適なソリューションを選択する必要があります。私のiPadアプリには、UIViewControllerモーダルとして表示されUIModalPresentationFormSheet、で構成される がありUITableViewます。このテーブルにはUITextFields、セルごとに 2 つ含まれています。メソッドを呼び出すだけscrollToRowAtIndexPath:atScrollPosition:animated:textFieldDidBeginEditing:はうまくいきません。したがって、私は以下を作成しましたtableFooterView

- (void)viewDidLoad
{
    [super viewDidLoad];

    m_footerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, m_tableView.frame.size.width, 300.0f)];
    [m_footerView setBackgroundColor:[UIColor clearColor]];
    [m_tableView setTableFooterView:m_footerView];
    [m_footerView release];
}

アイデアは、キーボードが ではtableFooterViewなく を非表示にするということUITextFieldsです。したがって、tableFooterView十分に高くなければなりません。その後scrollToRowAtIndexPath:atScrollPosition:animated:textFieldDidBeginEditing:メソッドで使用できます。

キーボード通知のオブザーバーを追加することで、動的に表示および非表示にすることも可能だと思いますtableFooterViewが、まだ試していません。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear: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 
{
     [m_tableView setTableFooterView:m_footerView];
}

- (void)keyboardWillHide:(NSNotification *)notification 
{
     [m_tableView setTableFooterView:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
于 2012-09-15T07:51:53.663 に答える
0

最良の方法は、UITableViewController を使用することだと思います。

UIViewController にUITableView が必要な場合は、UITableViewController が埋め込まれた ContentView を作成し、UIViewController の viedDidLoad に次の行を追加します。

self.tableView = ((UITableViewController*)self.childViewControllers[0]).tableView;
self.tableView.delegate = self;
self.tableView.dataSource = self;

簡単 ;)

于 2014-06-06T15:29:10.190 に答える
0

これは、iOS7 カレンダー アプリの「イベント編集」画面に触発された私のソリューションです。

このソリューションの重要なポイントの 1 つは、ユーザーがテーブルをスクロールするとキーボードが閉じられることです。

実装:

1) 選択したテキスト フィールドを格納するプロパティを追加します。

@property (strong) UITextField *currentTextField;

ユーザーがテーブルをスクロールするときにキーボードを非表示にする必要があるかどうかを確認するために使用する BOOL 変数。

BOOL hideKeyboardOnScroll;

2) UITextField デリゲート コールバックを処理します。

#pragma mark - UITextFieldDelegate

- (void) textFieldDidBeginEditing: (UITextField *) textField {
    self.currentTextField = textField;
}

- (void) textFieldDidEndEditing: (UITextField *) textField {
    self.currentTextField = nil;
}

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

    CGPoint newContentOffset = CGPointZero;
    if (tableView.contentSize.height > tableView.frame.size.height) {
        newContentOffset.y = MIN(tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);
    }
    [tableView setContentOffset: newContentOffset animated: YES];

    return YES;
}

3) UIScrollViewDelegate メソッドを処理して、そのユーザーのスクロール ビューを確認します。

#pragma mark - UIScrollViewDelegate

- (void) scrollViewDidScroll: (UIScrollView *) scrollView {
    if (hideKeyboardOnScroll == YES) {
        [self.currentTextField resignFirstResponder];
    }
}

4) viewcontroller の [viewWillAppear] メソッドでキーボード通知をサブスクライブし、[viewWillDisappear] メソッドでサブスクライブを解除します。

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

    [ [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];

    [ [NSNotificationCenter defaultCenter] removeObserver: self name: UIKeyboardDidShowNotification object: nil];
    [ [NSNotificationCenter defaultCenter] removeObserver: self name: UIKeyboardWillHideNotification object: nil];    
}

5) キーボード通知を処理します。

- (void) keyboardWillShow: (NSNotification *) notification {
    CGRect keyboardFrame = [ [ [notification userInfo] objectForKey: UIKeyboardFrameBeginUserInfoKey] CGRectValue];

    // Find cell with textfield.
    CGRect textFieldFrame = [tableView convertRect: self.currentTextField.frame fromView: self.currentTextField];
    NSIndexPath *indexPath = [tableView indexPathForRowAtPoint: textFieldFrame.origin];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
    //

    // Shrink tableView size.
    CGRect tableViewFrame = tableView.frame;
    tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width,
                             self.view.frame.size.height - tableView.frame.origin.y - keyboardFrame.size.height);
    //

    // Check if cell is visible in shrinked table size.
    BOOL cellIsFullyVisible = YES;
    if ( cell.frame.origin.y < tableView.contentOffset.y ||
        (cell.frame.origin.y + cell.frame.size.height) > (tableView.contentOffset.y + tableView.frame.size.height) ) {
        cellIsFullyVisible = NO;
    }
    //

    // If cell is not fully visible when scroll table to show cell;
    if (cellIsFullyVisible == NO) {
        CGPoint contentOffset = CGPointMake(tableView.contentOffset.x, CGRectGetMaxY(cell.frame) - tableView.frame.size.height);
        if (cell.frame.origin.y < tableView.contentOffset.y) {
            contentOffset.y = cell.frame.origin.y;
        }
        contentOffset.y = MAX(0, contentOffset.y);

        // For some reason [setContentOffset] is called without delay then
        // this code may not work for some cells. That why we call it with brief delay.
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [UIView animateWithDuration: 0.5 animations:^{
                [tableView setContentOffset: contentOffset animated: NO];
            } completion: ^(BOOL finished) {
                hideKeyboardOnScroll = YES;
            }];
        });
    } else {
        hideKeyboardOnScroll = YES;
    }
    //

    // Finally restore original table frame.
    tableView.frame = tableViewFrame;
    //
}

- (void) keyboardWillHide: (NSNotification *) notification {
    [super keyboardWillHide: notification];

    hideKeyboardOnScroll = NO;
}
于 2014-08-21T14:43:31.110 に答える
0

UITableViewController の使用時に別のバグを発見しました。キーボードが表示されたときに自動的にスクロールしませんでした。UITableView の contentInsetAdjustmentBehavior = .never が原因であることに気付きました。

于 2019-07-03T18:30:36.553 に答える