ios - keyboardtype - uitableview scroll




텍스트 필드가 선택되면 UITableView 스크롤 만들기 (20)

시행 착오 끝에 많은 것을 포기하고 질문합니다. 나는 비슷한 문제를 가진 많은 사람들을 보았지만 모든 해답을 올바르게 얻을 수는 없습니다.

나는 사용자 정의 셀로 구성되어있는 UITableView 있습니다. 셀은 5 개의 서로 다른 텍스트 필드로 구성됩니다 (일종의 그리드와 같습니다).

스크롤 및 UITableView 아래쪽에있는 셀을 편집 할 때 키보드 위에 제대로 셀을 가져올 수 없습니다.

나는보기 크기를 바꾸는 것에 대해 이야기하는 많은 해답을 보았다. 그러나 그들 중 누구도 지금까지 훌륭하게 일하지 않았다.

"구체적인"코드 예제를 사용하여 "올바른"방법을 명확히 할 수 있습니까?


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


나는 같은 문제가 있었지만 그것이 하나의 견해에서만 나타난다는 것을 알아 차렸다. 그래서 저는 컨트롤러의 차이점을 찾기 시작했습니다.

스크롤 동작이 - (void)viewWillAppear:(BOOL)animated super 인스턴스의 - (void)viewWillAppear:(BOOL)animated 으로 설정되었음을 알았습니다.

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

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

UIViewController 또는 UITableViewController 를 사용하면 상관 없습니다. UIViewController 에서 self.view의 하위 뷰로 UITableView 를 배치하여이를 확인했습니다. 그것은 같은 행동이었다. 보기가 스크롤을 허용하지 않는 경우 [super viewWillAppear:animated]; 실종되었다.


나는 애플의 애플 리케이션의 동작과 일치하는 솔루션을 생각해 냈다.

첫째, 당신의 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];
    }
}

이제 여기에 스크롤 비트가 있습니다. 먼저 크기를 약간 조정 한 다음, 보이는 영역에있는 곳을 확인하고 스크롤하려는 rect를 텍스트 필드의 가운데 위 또는 아래의 절반보기로 설정합니다 어디에서 볼 수 있습니다. 이 경우 우리는 UITextFields의 배열과 그것들을 추적하는 enum을 가지므로 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];
}

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


내 접근 방식 :

먼저 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);}];

너희들이 이미 모든 것을 읽는 해결책을 얻길 바랍니다. 그러나 나는 다음과 같이 나의 해결책을 발견했다. 나는 당신이 이미 UITextField 가있는 셀을 가질 것으로 기대하고있다. 따라서 텍스트 필드의 태그에 행 인덱스를 유지하기 만하면됩니다.

cell.textField.tag = IndexPath.row;

다음과 같이 전역 범위를 사용하여 UITextField 인스턴스 인 activeTextField 만듭니다.

@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 가 키보드에 의해 더 이상 숨겨지지 않기를 바랍니다.


스크롤을 수행하는 함수는 훨씬 간단 할 수 있습니다.

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

그게 전부 야. 전혀 계산이 없습니다.


UITableViewController 를 사용할 수 있다면 무료로 기능을 사용할 수 있습니다. 그러나 UITableView 뿐만 아니라 여러보기가 필요한 경우가 종종 있습니다.

여기에 제시된 솔루션 중 일부는 iOS ≥4에서 작동하지 않으며 일부는 iPad 또는 가로 모드에서 작동하지 않으며 일부는 블루투스 키보드 (일부 스크롤을 원하지 않는 곳)에서 작동하지 않으며 일부는 작동하지 않습니다 여러 텍스트 필드 사이를 전환 할 때 작동합니다. 따라서 솔루션을 선택하는 경우 이러한 사례를 테스트해야합니다. 이것은 우리가 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 클래스전체 코드는 다음과 같습니다. 테스트하려면 위에서 언급 한 시나리오를 테스트 할 수있는 "전체 목록"하위 창을 사용하십시오.


스위프트를 위한 가장 간단한 솔루션 :

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
    }

UITableView가 UITableViewController의 하위 클래스에 의해 관리되고 UITableView가 아니라 UITableViewController 인 경우에는 모든 스크롤을 자동으로 관리해야합니다. 다른 모든 주석은 실제로 구현하기가 매우 어렵습니다.

좋은 예제는 apple 예제 코드 프로젝트 : TaggedLocations를 참조하십시오.

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


나는 구글과 스택 오버 플로우 ()를 통해 발견 된 수많은 솔루션을 언급 한 후에 나 자신만으로 이러한 문제를 해결했다.

먼저 UIScrollView의 IBOutlet을 설정했는지 확인한 다음 http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html 자세히 살펴보십시오 . 마지막으로, 배경을 스크롤 할 수 있지만 키보드가 여전히 텍스트 필드를 다루는 경우 다음 코드를 살펴보십시오.

// 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 조건의 가장 큰 차이점은 나는 애플이 스크롤 거리를 계산하고 텍스트 필드가 키보드로 덮여 있는지 여부를 판단하는 것이 정확하지 않으므로 위와 같이 수정했다.

작동하는지 알려주세요.


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

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

매우 흥미로운 토론 스레드, 나도 같은 문제에 직면 더 나쁜 수 있습니다

  1. 맞춤형 셀을 사용하고 있는데 텍스트 필드가 그 안에 있습니다.
  2. UIViewController를 사용하여 내 요구 사항을 충족시켜야하므로 UITableViewController를 활용할 수 없습니다.
  3. 내 테이블 셀에 필터 / 정렬 기준이 있습니다. 즉, UR 셀은 계속해서 인덱스 경로를 변경하고 추적하며 계속 도움이되지 않습니다.

그래서 여기의 스레드를 읽고 내 버전을 구현하여 iPad에서 내 콘텐츠를 가로 모드 로 푸시하는 데 도움이되었습니다 . 여기에 코드가 있습니다 (이것은 바보 같은 증거는 아니지만 모두 내 문제가 해결되었습니다). 먼저 편집 할 때 텍스트 필드를 viewcontroller로 보내고 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


이 soluton 나를 위해 일하는 라인을 유의하시기 바랍니다

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

이것은 iPad에서도 완벽하게 작동합니다.

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

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

Swift 에서 UITableViewCell의 UITextField의 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)
}

그래서 이러한 현재의 솔루션을 사용하려고 힘든 시간을 보냈을 때 나는 마침내 일을 잘 처리하고 새로운 애니메이션 블록을 사용하도록 업데이트했습니다. 내 대답은 위의 Ortwin의 대답을 전적으로 기반으로 합니다.

그래서 위의 코드가 어떤 이유로 든 나를 위해 일하지 않았습니다. 내 설정은 다른 사람들과 상당히 유사하게 보였지만, 아마도 iPad 나 4.3에 있었기 때문에 가능했을 것입니다. 그것은 엉뚱한 수학을하고 화면에서 내 tableview 촬영.

내 솔루션의 최종 결과보기 : http://screencast.com/t/hjBCuRrPC (사진을 무시하십시오 : - P)

그래서 Ortwin이하는 일의 요지로 갔지만 원점을 더하기 위해 수학을하는 방법을 바 꾸었습니다. 키보드의 높이로 테이블보기의 높이와 크기. 그 결과에서 창 높이를 빼면 내가 얼마나 많은 교차로가 있는지 알려줍니다. 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;
}

나는 거의 동일한 접근법을 시도해 보았고 동일하고 더 간단한 코드를 만들었다. 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];

    }

당신이 사용하는 경우 Three20, 다음 사용 autoresizesForKeyboard속성을. 보기 컨트롤러의 -initWithNibName:bundle메서드로 설정하면됩니다.

self.autoresizesForKeyboard = YES

이것은 다음을 담당합니다.

  1. 키보드 알림 듣기 및 테이블보기 프레임 조정
  2. 첫 번째 응답자로 스크롤

완료 및 완료.


더 많은 스트림 라이닝 된 솔루션. 그것은 UITextField 델리게이트 메소드에 들어가기 때문에, UIKeyboard 통지가 필요하지 않습니다.

구현시주의 사항 :

kSettingsRowHeight - UITableViewCell의 높이입니다.

offsetTarget 및 offsetThreshold는 kSettingsRowHeight에서 벗어났습니다. 다른 행 높이를 사용하는 경우 해당 값을 point의 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;

}





scroll