programing

텍스트 필드를 선택할 때 UITableView 스크롤 만들기

padding 2023. 5. 18. 20:49
반응형

텍스트 필드를 선택할 때 UITableView 스크롤 만들기

많은 시행착오 끝에 포기하고 질문합니다.저는 비슷한 문제를 가진 사람들을 많이 보았지만, 일을 하기 위한 모든 답을 제대로 얻을 수 없습니다.

나는 있습니다UITableView사용자 지정 셀로 구성되어 있습니다.셀은 5개의 텍스트 필드로 구성되어 있습니다(예: 그리드).

아래쪽의 셀을 스크롤하고 편집하려고 할 때UITableView키보드 위에 셀을 제대로 배치할 수 없습니다.

보기 크기 변경 등에 대해 이야기하는 답변을 많이 보았습니다.하지만 지금까지 제대로 작동한 사람은 아무도 없었습니다.

구체적인 코드 예를 들어 "올바른" 방법을 설명할 수 있는 사람이 있습니까?

UIViewController 대신 UITableViewController를 사용하면 자동으로 사용됩니다.

스크롤하는 기능은 훨씬 간단할 수 있습니다.

- (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];
}

바로 그겁니다.계산이 전혀 없습니다.

저는 매우 유사한 것을 하고 있습니다. 일반적인 것입니다. 코드에 특정한 것을 계산할 필요가 없습니다.코드에 대한 설명만 확인하면 됩니다.

My UIViewController에서.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

My UIViewController.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()
        }
    }
}

Swift 3의 가장 간단한 솔루션은 Bartwomiej Semańczyk 솔루션을 기반으로 합니다.

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)
    })
}

저도 같은 문제가 있었지만 하나의 보기에만 표시된다는 것을 알게 되었습니다.그래서 저는 컨트롤러의 차이점을 찾기 시작했습니다.

스크롤 동작은 다음과 같이 설정되어 있습니다.- (void)viewWillAppear:(BOOL)animated초례의

따라서 다음과 같이 구현해야 합니다.

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

그리고 당신이 사용해도 상관없습니다.UIViewController또는UITableViewControllera를 넣어 확인했습니다.UITableView자기의 부감으로서에서 보기UIViewController그것은 같은 행동이었습니다.호출 시 보기를 스크롤할 수 없습니다.[super viewWillAppear:animated];누락되었습니다.

제가 여기 게시물을 전부 읽지 않았기 때문에 이것을 놓쳤을 수도 있지만, 제가 생각해 낸 것은 기만적으로 간단해 보입니다.저는 이것을 모든 상황에서 테스트하는 실수를 저지르지는 않았지만, 그것은 잘 작동할 것으로 보입니다.

간단히 내용을 조정합니다.키보드 높이를 기준으로 표 보기를 삽입한 다음 셀을 맨 아래로 스크롤합니다.

- (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;
    }];
}

이것은 너무 단순합니까?제가 뭔가를 놓쳤나요? 지금까지는 저에게 잘 먹히지만, 제가 말했듯이, 저는 그것을 잘못 이해하지 못했습니다.

저는 애플 앱의 행동에 맞는 해결책을 생각해냈다고 생각합니다.

먼저, 보기에 표시됨: 키보드 알림을 구독하면 키보드가 언제 표시되고 숨길지 알 수 있습니다. 그러면 시스템에서 키보드 크기를 알려주지만 등록 취소를 잊지 마십시오.

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

키보드가 표시되면 표시되는 영역과 일치하도록 테이블 보기의 크기를 조정할 수 있도록 아래와 유사한 방법을 구현합니다.여기서는 키보드 상태를 개별적으로 추적하여 테이블을 전체 높이로 설정할 시기를 선택할 수 있습니다. 모든 필드 변경에 대해 이러한 알림이 표시되므로 직접 보기를 선택할 수 있습니다.키보드 WillHide:을(를) 구현하는 것을 잊지 말고 테이블 보기 크기를 수정할 적절한 위치를 선택합니다.

-(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 배열과 이를 추적하는 열거형이 있으므로 행 높이에 행 번호를 곱하면 이 외부 뷰 내 프레임의 실제 오프셋이 제공됩니다.

- (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];
}

이것은 꽤 잘 작동하는 것 같습니다.

사용할 수 있는 경우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 클래스의 전체 코드입니다.테스트하려면 위에서 언급한 시나리오를 테스트할 수 있는 "전체 목록" 하위 창을 사용합니다.

Swift를 위한 가장 간단한 솔루션:

override func viewDidLoad() {
    super.viewDidLoad()
    
    searchBar?.becomeFirstResponder()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size.height {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    UIView.animateWithDuration(0.2, animations: { self.table_create_issue.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) })
    // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
    }

Swift 4.2 이상의 경우

override func viewDidLoad() {
    super.viewDidLoad()
    searchBar?.becomeFirstResponder()
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: UIResponder.keyboardDidShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: UIResponder.keyboardDidHideNotification, object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

 @objc func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
            let keyboardHeight = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue.size.height
            accountSettingsTableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0)
        
    }
}
@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2, animations: { self.accountSettingsTableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) })}
}

저는 여러분들이 이미 그것들을 읽는 해결책을 가지고 있기를 바랍니다.하지만 저는 다음과 같이 해결책을 찾았습니다.당신은 이미 당신과 함께 휴대폰을 가지고 있을 것으로 기대됩니다.UITextField준비하는 동안 행 인덱스를 텍스트 필드의 태그에 유지합니다.

cell.textField.tag = IndexPath.row;

다음을 작성합니다.activeTextFieldUITextField과 같습니다.

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

}

이제 한 가지가 남았어요, 전화해요.registerForKeyboardNotifications를 의에방법으로.ViewDidLoad방법은 다음과 같습니다.

- (void)viewDidLoad {

    [super viewDidLoad];

    // Registering keyboard notification

    [self registerForKeyboardNotifications];

    // Your codes here...

}

당신은 끝났으니, 당신의.textFields키보드로 더 이상 숨기지 않습니다.

여러 개의 답변(특히 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

적합한 보기를 사용하여 텍스트 필드를 배치하는 경우(Jeff Lamarchhe에서) 위임 방법을 사용하여 테이블 보기를 스크롤할 수 있습니다.

(참고: 내 텍스트 필드는 테이블 보기의 행과 동일한 인덱스를 가진 배열에 저장됩니다)

- (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];
    }

키보드 알림은 작동하지만 Apple의 샘플 코드는 스크롤 보기가 창의 루트 보기라고 가정합니다.보통은 그렇지 않습니다.탭 바 등을 보정해야 올바른 오프셋을 얻을 수 있습니다.

그것은 듣기보다 쉽습니다.다음은 UITableViewController에서 사용하는 코드입니다.숨겨진 Rect와 키보드라는 두 개의 인스턴스 변수가 있습니다.보여줍니다.

// 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;
}

사용하는 경우Three20그런 다음 사용합니다.autoresizesForKeyboard의 뷰 컨트롤러하면 됩니다.-initWithNibName:bundle방법

self.autoresizesForKeyboard = YES

이는 다음을 처리합니다.

  1. 키보드 알림 청취 및 표 보기 프레임 조정
  2. 첫 번째 응답자로 스크롤

완전히 끝.

내 접근 방식:

먼저 UITextField를 하위 분류하고 indexPath 속성을 추가합니다.감방에서...메서드 i가 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);}];

FieldShould/WillBegin... 등 텍스트로 이동합니다.

키보드가 사라지면 다음을 사용하여 키보드를 반대로 조작해야 합니다.

[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, 0);}];

Swift 4.2 완전 솔루션

저는 키보드를 표시하거나 숨기거나 변경할 때 추가 공간을 추가하여 작업을 단순화하는 프로토콜 세트로 GIST를 만들었습니다.

특징:

  • 키보드 프레임 변경(예: 이모지 → 일반 키보드와 같은 키보드 높이 변경)과 올바르게 작동합니다.
  • UITableView 예제에 대한 TabBar 및 ToolBar 지원(다른 예제에서는 잘못된 inset을 수신함)
  • 동적 애니메이션 기간(하드 코딩되지 않음).
  • 사용자의 목적에 맞게 쉽게 수정할 수 있는 프로토콜 지향 접근 방식.

사용.

일부 스크롤 뷰를 포함하는 뷰 컨트롤러의 기본 사용 예(테이블 뷰도 물론 지원됨).

class SomeViewController: UIViewController {
  @IBOutlet weak var scrollView: UIScrollView!

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    addKeyboardFrameChangesObserver()
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeKeyboardFrameChangesObserver()
  }
}

extension SomeViewController: ModifableInsetsOnKeyboardFrameChanges {
  var scrollViewToModify: UIScrollView { return scrollView }
}

코어: 프레임 변경 관찰자

KeyboardChangeFrameObserver키보드 프레임이 변경될 때마다 이벤트가 발생합니다(표시, 숨기기, 프레임 변경 포함).

  1. addKeyboardFrameChangesObserver()viewWillAppear()또는 유사한 방법.
  2. removeKeyboardFrameChangesObserver()viewWillDisappear()또는 유사한 방법.

구현: 스크롤 보기

ModifableInsetsOnKeyboardFrameChanges 프토추UIScrollView핵심 프로토콜 지원.키보드 프레임을 변경할 때 스크롤 뷰의 삽입값을 변경합니다.

클래스에서 스크롤 보기를 설정해야 합니다. 키보드 프레임 변경 시 삽입값이 증가하거나 감소합니다.

var scrollViewToModify: UIScrollView { get }

더욱 간소화된 솔루션.UITextField 위임 메서드에 포함되므로 UITextField 알림을 사용하여 혼동할 필요가 없습니다.

구현 참고 사항:

k 설정 행높이 - UITableViewCell의 높이입니다.

간격띄우기목표값 및 간격띄우기임계값이 kSettingsRow를 벗어난 경우높이. 다른 행 높이를 사용하는 경우 해당 값을 점의 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;

}

사용하다UITextField's delegate 예:

스위프트

func textFieldShouldBeginEditing(textField: UITextField) -> bool {
  let txtFieldPosition = textField.convertPoint(textField.bounds.origin, toView: yourTableViewHere)
  let indexPath = yourTablViewHere.indexPathForRowAtPoint(txtFieldPosition)
  if indexPath != nil {
     yourTablViewHere.scrollToRowAtIndexPath(indexPath!, atScrollPosition: .Top, animated: true)
  }
  return true
}

목표-C

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
  CGPoint txtFieldPosition = [textField convertPoint:CGPointZero toView: yourTablViewHere];
  NSLog(@"Begin txtFieldPosition : %@",NSStringFromCGPoint(txtFieldPosition));
  NSIndexPath *indexPath = [yourTablViewHere indexPathForRowAtPoint:txtFieldPosition];

  if (indexPath != nil) {
     [yourTablViewHere scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  }
  return YES;
}

테이블에 텍스트 필드가 있으므로 가장 좋은 방법은 테이블 크기를 조정하는 것입니다. tableView.frame을 키보드 크기만큼 작게 설정한 다음(165픽셀 정도) 키보드가 제거되면 다시 확장해야 합니다.

사용자 스크롤을 원하지 않는 경우에도 선택적으로 테이블 보기에 대한 사용자 상호 작용을 비활성화할 수 있습니다.

이것은 완벽하게 작동하며, 아이패드에서도 작동합니다.

- (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];
        }

저는 거의 같은 접근법을 시도했고 동일한 것에 대해 더 간단하고 작은 코드를 생각해냈습니다.IBOutlet iTextView를 만들고 IB의 UITTextView와 연결했습니다.

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

    }

그래서 현재의 솔루션을 사용하기 위해 몇 시간 동안의 고된 작업 끝에 (완전히 실패한) 마침내 잘 작동하게 되었고, 새로운 애니메이션 블록을 사용하도록 업데이트했습니다.제 답변은 전적으로 위의 오트윈의 답변에 기초하고 있습니다.

그래서 어떤 이유로든 위의 코드는 저에게 효과가 없었습니다.제 설정은 다른 것들과 꽤 비슷해 보였지만, 아마도 제가 아이패드나 4.3을 사용했기 때문일 것입니다.전혀 모릅니다.그것은 이상한 계산을 하고 화면에서 제 테이블 뷰를 촬영하는 것이었습니다.

내 솔루션의 최종 결과 보기: http://screencast.com/t/hjBCuRrPC (사진은 무시해 주세요. :-P)

그래서 저는 오트윈이 무엇을 하고 있는지에 대한 요점을 따랐지만, 그것이 수학을 하는 방법을 바꿔 원점.y와 크기를 합쳤습니다.키보드 높이와 내 테이블 보기 높이.그 결과에서 창 높이를 빼면 교차로가 얼마나 되는지 알 수 있습니다.0보다 크면 프레임 높이 애니메이션을 수행합니다.

또한 1) 애니메이션이 완료될 때까지 셀로 스크롤하기 위해 기다리는 중 2) 키보드를 숨길 때 UIView Animation OptionBeginFromCurrentState 옵션을 사용하여 해결된 몇 가지 재도약 문제가 있습니다.

몇 가지 주의할 점이 있습니다.

  • _topmostRowBeforeKeyboardWasShow & _originalFrame은 헤더에 선언된 인스턴스 변수입니다.
  • self.guestEntryTableView가 내 테이블입니다. 보기(외부 파일에 있습니다)
  • IASKCGrectSwap은 프레임의 좌표를 뒤집는 Ortwin의 방법입니다.
  • 표의 높이만 업데이트합니다. 표의 최소 50px가 표시되는 경우 보기
  • UIViewController에 있지 않기 때문에 자신이 없습니다.보기, 그래서 테이블을 원래 프레임으로 되돌립니다. 보기

다시 말씀드리지만, 만약 제가 오트윈이 답의 핵심을 제공하지 않았다면 저는 이 답에 접근하지 못했을 것입니다.코드는 다음과 같습니다.

- (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;
}

이 솔루션은 저에게 적합합니다. 주의하십시오.

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

매우 흥미로운 토론 스레드, 나도 같은 문제에 직면했습니다. 왜냐하면 더 나쁜 문제일 수 있기 때문입니다.

  1. 저는 커스텀 셀을 사용하고 있었고 텍스트 필드는 그 안에 있었습니다.
  2. 요구 사항을 충족하기 위해 UIViewController를 사용해야 했기 때문에 UITableViewController를 활용할 수 없었습니다.
  3. 테이블 셀에 필터/정렬 기준이 있습니다. 셀이 계속 변경되고 인덱스 경로를 추적하므로 모든 것이 도움이 되지 않습니다.

여기 있는 스레드를 읽고 iPad의 콘텐츠를 가로 모드로 끌어올리는 데 도움이 되는 버전을 구현했습니다.여기 코드가 있습니다(이것이 전부는 아니지만 문제를 해결했습니다).먼저 사용자 지정 셀 클래스에 대리자가 있어야 합니다. 편집이 시작되면 텍스트 필드를 뷰 컨트롤러로 보내고 활성 필드 = 해당 텍스트 필드를 설정합니다.

가로 모드만 처리하도록 구현됨

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

    }


}

UIKeyboard WillHide 알림이 전송되면 호출됩니다.

- (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

Google과 Stack Overflow를 통해 발견된 수많은 솔루션을 참조한 후 저는 이러한 문제를 혼자서 해결했습니다.

먼저 UIScrollView의 IBOutlet을 설정했는지 확인한 다음 Apple Doc: 키보드 관리를 자세히 살펴보시기 바랍니다.마지막으로 배경을 스크롤할 수 있지만 키보드가 여전히 텍스트 필드를 덮고 있다면 다음 코드를 확인하십시오.

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

이 조각과 애플의 주요 차이점은 if 조건에 있습니다.저는 애플의 스크롤 거리 계산과 키보드로 가려진 텍스트 필드의 상태가 정확하지 않다고 생각하여 위와 같이 수정하였습니다.

효과가 있으면 알려주세요.

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)
}

스위프트 4.2의 작은 변형...

UITableView에는 많은 섹션이 있었지만 부동 헤더 효과를 피해야 했기 때문에 "dummyView"를 사용했습니다.높이" 접근법은 스택 오버플로의 다른 부분에서 볼 수 있습니다.이것이 이 문제에 대한 저의 해결책입니다(키보드 + 도구 모음 + 제안에도 사용 가능).

클래스 상수로 선언:

let dummyViewHeight: CGFloat = 40.0

그리고나서

override func viewDidLoad() {
    super.viewDidLoad()
    //... some stuff here, not needed for this example

    // Create non floating header
    tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: dummyViewHeight))
    tableView.contentInset = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: 0, right: 0)

    addObservers()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeObservers()
}

그리고 여기 모든 마법들이...

@objc func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let keyboardHeight = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue.size.height
        tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
        tableView.contentInset = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: keyboardHeight, right: 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.25) {
        self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: self.dummyViewHeight))
        self.tableView.contentInset = UIEdgeInsets(top: -self.dummyViewHeight, left: 0, bottom: 0, right: 0)
    }
}

다른 쉬운 방법(한 섹션에서만 작동)

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

UITableView가 UITableViewController가 아닌 UITableViewController의 하위 클래스에 의해 관리되고 텍스트 필드 대리자가 UITableViewController인 경우 모든 스크롤을 자동으로 관리해야 합니다. 다른 모든 설명은 실제로 구현하기가 매우 어렵습니다.

좋은 예는 애플 예제 코드 프로젝트를 참조하십시오.태그가 지정된 위치입니다.

자동으로 스크롤되는 것을 볼 수 있지만, 이를 수행하는 코드는 없는 것 같습니다.이 프로젝트에는 사용자 정의 테이블 뷰 셀도 있으므로, 이를 기준으로 응용 프로그램을 빌드하면 원하는 결과를 얻을 수 있습니다.

이것이 제가 어떻게 이 일을 만들었는지입니다. Sam Ho와 Marcel W의 대답과 제가 만든 형편없는 코드에 대한 버그 수정의 혼합입니다.UITableViewController를 사용하고 있었습니다.이제 키보드가 표시되면 테이블의 크기가 올바르게 조정됩니다.

viewDidLoad추가한 항목:

self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

나는 전화하는 것을 잊었습니다.super에있 동서한 것등어의 viewWillAppear그리고.awakeFromNib이걸 다시 넣었습니다.

언급URL : https://stackoverflow.com/questions/594181/making-a-uitableview-scroll-when-text-field-is-selected

반응형