[ios] 키보드가있을 때 편집을 시작할 때 UITextField를 위로 올리려면 어떻게해야합니까?

iOS SDK를 사용하여 :

나는이 UIViewUITextField키보드를 가지고 있음을의. 나는 그것을 할 수 있어야합니다.

  1. UIScrollView키보드를 불러 온 후 다른 텍스트 필드를 보려면 의 내용을 스크롤 할 수 있습니다.

  2. 자동으로 “점프”(위로 스크롤) 또는 단축

나는 내가 필요하다는 것을 안다 UIScrollView. 내의 클래스를 변경 해봤 UIViewA를 UIScrollView하지만, 난 여전히 위 또는 아래로 텍스트 상자를 스크롤 할 수 없어요.

a UIView와 a 가 모두 필요 UIScrollView합니까? 하나는 다른 안으로 들어가나요?

활성 텍스트 필드로 자동 스크롤하려면 무엇을 구현해야합니까?

가능한 한 많은 구성 요소 설정이 Interface Builder에서 수행됩니다. 필요한 코드 만 작성하고 싶습니다.

참고 : 내가 작업하고 있는 UIView(또는 UIScrollView)은 정상적으로 작동 UITabBar해야하는 탭 바 ( )에 의해 나타납니다 .


편집 : 키보드가 나타날 때만 스크롤 막대를 추가하고 있습니다. 필요하지는 않지만 사용자가 텍스트 상자를 스크롤하고 변경할 수 있기 때문에 더 나은 인터페이스를 제공한다고 생각합니다.

UIScrollView키보드가 위아래로 움직일 때의 프레임 크기를 변경하는 곳에서 작동 합니다. 나는 단순히 다음을 사용하고 있습니다 :

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x,
                     scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x,
       scrollView.frame.origin.y,
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

그러나 이것은 가시 영역의 하단 텍스트 필드를 자동으로 “위로 이동”하거나 가운데에 두지 않습니다. 이것이 내가 정말로 원하는 것입니다.



답변

  1. ScrollViewiPhone 화면에 맞지 않는 내용 만 있으면됩니다. ( ScrollView구성 요소의 슈퍼 뷰로를 추가하는 경우TextField 키보드가 나타날 때 스크롤 필요하지 않습니다.)

  2. 방지하는 표준 방법 TextField키보드로 키보드 은 키보드가 표시 될 때마다보기를 위 / 아래로 이동하는 것입니다.

샘플 코드는 다음과 같습니다.

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[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];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

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


답변

또한 UIScrollView여러 개의 작곡에 많은 문제가 UITextFields있었고 그 중 하나 이상이 편집 중 키보드에 의해 가려 질 수 있습니다.

UIScrollView스크롤이 제대로되지 않으면 고려해야 할 사항이 있습니다 .

1) contentSize가 UIScrollView프레임 크기 보다 큰지 확인하십시오 . 이해하는 방법은 UIScrollViews(가)이다 UIScrollViewcontentSize에 정의 된 내용에 보는 창 같다. 따라서 UIScrollview어디에서나 스크롤하려면 contentSize가.보다 커야합니다 UIScrollView. 그렇지 않으면 contentSize에 정의 된 모든 항목이 이미 표시되므로 스크롤이 필요하지 않습니다. BTW, 기본 contentSize =CGSizeZero .

2) 이제는 이것이 UIScrollView실제로 “콘텐츠”의 창 이라는 것을 이해 했으므로 키보드가 UIScrollView's보기 “창”을 가리지 않도록하는 방법은 키보드가 UIScrollView있을 때 UIScrollView창 을 갖도록 크기를 조정하는 것입니다. 크기는 원래 UIScrollView프레임 크기 와 높이에서 키보드 높이를 뺀 크기 입니다. 이렇게하면 창이 작은 가시 영역 만 확보 할 수 있습니다.

3) 캐치가 있습니다 : 처음 이것을 구현했을 때 CGRect편집 된 텍스트 필드 를 가져 와서 UIScrollView'sscrollRecToVisible 메소드를 호출 해야한다고 생각 했습니다 . UITextFieldDelegate메서드 textFieldDidBeginEditing를 호출 하여 메서드 를 구현했습니다 scrollRecToVisible. 이것은 실제로 스크롤 것이 이상한 부작용과 협력 스냅UITextField위치로. 가장 오랫동안 나는 그것이 무엇인지 알 수 없었습니다. 그런 다음 textFieldDidBeginEditingDelegate 메서드를 주석 처리하고 모두 작동합니다 !! (???). 그것이 UIScrollView실제로 암시 적으로 현재 편집 UITextField된 것을 볼 수있는 창에 암시 적으로 가져 온다고 생각합니다 . UITextFieldDelegate메소드의 구현 과 이후의 호출 scrollRecToVisible은 중복되었으며 이상한 부작용의 원인이었습니다.

그래서 여기에 제대로 스크롤하는 단계입니다 UITextFieldA의 UIScrollView장소 때 키보드가 나타납니다으로는.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. 키보드 알림 등록 viewDidLoad
  2. 키보드 노 티피 케이션 등록 해제 viewDidUnload
  3. 이 있는지 확인 contentSize설정하고보다 큰 UIScrollView에서viewDidLoad
  4. 축소UIScrollView키보드가있는 경우
  5. 다시 되돌리기UIScrollView 키보드가 사라질 때.
  6. 키보드 알림은이 때마다 전송되기 때문에 키보드가 이미 화면에 표시되어있는 경우 감지하는 바르를 사용하여 UITextField키보드를 피하기 위해 이미 존재하는 경우에도 탭되고 축소UIScrollView이미 때 수축을

한 가지주의해야 할 점은 UIKeyboardWillShowNotification다른 키보드를 탭하면 키보드가 이미 화면에 있어도 작동 한다는 것 UITextField입니다. UIScrollView키보드가 이미 화면에있을 때 크기 조정을 피하기 위해 ivar을 사용 하여이 문제를 해결했습니다 . UIScrollView키보드가 이미있을 때 실수로 크기를 조정하면 재앙이 생길 것입니다!

이 코드가 여러분의 많은 두통을 덜어 주길 바랍니다.


답변

docs에 제공된대로 실제로 Apple 구현을 사용하는 것이 가장 좋습니다 . 그러나 이들이 제공하는 코드에 결함이 있습니다. keyboardWasShown:주석 바로 아래 에있는 부분을 다음으로 대체하십시오 .

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

Apple 코드의 문제점은 다음과 같습니다. (1) 포인트가 뷰의 프레임 내에 있는지 항상 계산하지만 포인트 ScrollView이므로 이미 스크롤되어 해당 오프셋을 고려해야합니다.

origin.y -= scrollView.contentOffset.y

(2) 그들은 키보드의 높이에 따라 contentOffset을 이동 시키지만, 반대를 원합니다 ( contentOffset화면에 보이지 않는 높이가 아닌 높이 로 이동하고 싶습니다 ).

activeField.frame.origin.y-(aRect.size.height)


답변

다음 textFieldDidBeginEditting과 같이 textFieldDidEndEditing함수 를 호출하십시오 [self animateTextField:textField up:YES].

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField:textField up:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField:textField up:NO];
}

-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
    const int movementDistance = -130; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

    int movement = (up ? movementDistance : -movementDistance);

    [UIView beginAnimations: @"animateTextField" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

이 코드가 도움이 되길 바랍니다.

스위프트 2에서

func animateTextField(textField: UITextField, up: Bool)
{
     let movementDistance:CGFloat = -130
     let movementDuration: Double = 0.3

     var movement:CGFloat = 0
     if up
     {
         movement = movementDistance
     }
     else
     {
         movement = -movementDistance
     }
     UIView.beginAnimations("animateTextField", context: nil)
     UIView.setAnimationBeginsFromCurrentState(true)
     UIView.setAnimationDuration(movementDuration)
     self.view.frame = CGRectOffset(self.view.frame, 0, movement)
     UIView.commitAnimations()
}


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

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

스위프트 3

 func animateTextField(textField: UITextField, up: Bool)
    {
        let movementDistance:CGFloat = -130
        let movementDuration: Double = 0.3

        var movement:CGFloat = 0
        if up
        {
            movement = movementDistance
        }
        else
        {
            movement = -movementDistance
        }
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }


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

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


답변

TextFields를 사용하는 경우 :

1a) 사용 Interface Builder : 모든 텍스트 필드 선택 => 편집 => 포함 => ScrollView

1b) UIScrollView에 scrollField라는 텍스트 필드를 수동으로 포함

2) 세트 UITextFieldDelegate

3) 각각을 설정 textField.delegate = self;하거나Interface Builder )

4) 복사 / 붙여 넣기 :

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

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


답변

들어 범용 솔루션 , 여기에 구현하기위한 나의 접근 방식이었다 IQKeyboardManager을 .

여기에 이미지 설명을 입력하십시오

1 단계 : – 의 I 추가 글로벌 통지 UITextField, UITextViewUIKeyboard의 싱글 클래스입니다. 나는 그것을 IQKeyboardManager 라고 부른다 .

2 단계 : – 만약 발견 UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification또는 UITextViewTextDidBeginEditingNotification알림, 내가 좀하려고 topMostViewController로부터 인스턴스를 UIWindow.rootViewController계층 구조. 제대로 밝히기 위해서는 UITextField/ UITextView그것에서 topMostViewController.view의 프레임을 조정해야합니다.

Step3 :-topMostViewController.view 첫 번째 반응 UITextField/에 대한 예상 이동 거리를 계산 했습니다 UITextView.

4 단계는 : – 나는 이동 topMostViewController.view.frame예상 이동 거리에 따라 UP / DOWN.

Step5 :-UIKeyboardWillHideNotification , UITextFieldTextDidEndEditingNotification또는 UITextViewTextDidEndEditingNotification알림 이 발견 되면 계층 topMostViewController에서 인스턴스를 다시 가져 오려고 시도합니다 UIWindow.rootViewController.

Step6 :-topMostViewController.view 원래 거리 로 복원해야하는 방해 거리를 계산 했습니다.

Step7 :-topMostViewController.view.frame 방해 거리에 따라 회복 했습니다.

Step8 :- 앱로드시 싱글 톤 IQKeyboardManager 클래스 인스턴스를 인스턴스화 했으므로 앱의 모든 UITextField/ UITextView가 예상 이동 거리에 따라 자동으로 조정됩니다.

그게 다야 IQKeyboardManager을 당신을 위해 할 코드의 NO LINE 정말! 관련 소스 파일을 프로젝트로 끌어서 놓기 만하면됩니다. IQKeyboardManager 는 또한 장치 방향 , 자동 UI 도구 모음 관리 , KeybkeyboardDistanceFromTextField 및 훨씬 더 많은 것을 지원합니다.


답변

필자는 키보드에서 벗어나는 모든 텍스트 필드를 이동시키는 범용 드롭 UIScrollViewUITableViewUICollectionView서브 클래스를 구성했습니다.

키보드가 나타나려고 할 때 서브 클래스는 편집 할 서브 뷰를 찾고 키보드 팝업과 일치하는 애니메이션을 사용하여 뷰가 표시되도록 프레임과 컨텐츠 오프셋을 조정합니다. 키보드가 사라지면 이전 크기로 복원됩니다.

기본적으로 모든 설정, 즉 UITableView기반 인터페이스 또는 수동으로 배치 된보기로 구성된 설정에서 작동해야합니다 .

여기 : 키보드에서 텍스트 필드를 이동시키는 솔루션