web-dev-qa-db-ja.com

キーボードが表示されているときにUITextFieldを上に移動させるにはどうすればよいですか - 編集開始時に?

IOS SDKの場合

キーボードを起動するUIViewを持つUITextFieldがあります。私はそれができるようにする必要があります。

  1. キーボードが起動したら、UIScrollViewの内容をスクロールして他のテキストフィールドを見ることができるようにします

  2. 自動的に「ジャンプ」(上にスクロールする)または短縮

私はUIScrollViewが必要であることを知っています。 UIViewのクラスをUIScrollViewに変更しようとしましたが、それでもテキストボックスを上下にスクロールできません。

UIViewUIScrollViewの両方が必要ですか?一方はもう一方の内側に入りますか?

アクティブなテキストフィールドに自動的にスクロールするためには、何を実装する必要がありますか?

理想的には、できる限りコンポーネントの設定を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
}

しかし、これは自動的に "上に移動"したり、下のテキストフィールドを表示領域の中央に配置したりするものではありません。これは私が本当に望んでいることです。

1634
philfreo
  1. ScrollViewname__はiPhoneの画面に収まらない場合にのみ必要です。(コンポーネントのスーパービューとしてScrollViewname__を追加する場合。キーボードが表示されたときにTextFieldname__を上にスクロールするためだけに使用それからそれは必要ではないです。)

  2. キーボードで隠されずにtextfieldsname__を表示するための標準的な方法は、キーボードが表示されるたびにテキストフィールドを持つビューを上下に移動することです。

サンプルコードは次のとおりです。

#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];
}
999
RPDP

また、複数のUIScrollViewで構成されているUITextFieldsに多くの問題があり、そのうちの1つまたは複数は、編集中にキーボードによって隠されます。

UIScrollViewが適切にスクロールしない場合の考慮事項を次に示します。

1)contentSizeがUIScrollViewフレームサイズより大きいことを確認します。 UIScrollViewsを理解する方法は、UIScrollViewがcontentSizeで定義されたコンテンツの表示ウィンドウのようなものであることです。したがって、UIScrollviewをどこでもスクロールするには、contentSizeがUIScrollViewより大きくなければなりません。それ以外の場合、contentSizeで定義されたすべてがすでに表示されているため、スクロールは必要ありません。ところで、デフォルトのcontentSize = CGSizeZero

2)UIScrollViewは実際には「コンテンツ」へのウィンドウであることを理解したので、キーボードがUIScrollView'sを表示してウィンドウを覆い隠さないようにする方法は、UIScrollViewのサイズを変更して存在する場合、元のUIScrollView frame.size.heightからキーボードの高さを引いたサイズのUIScrollViewウィンドウがあります。これにより、ウィンドウはその小さな可視領域のみになります。

3)キャッチ:これを最初に実装したとき、編集したテキストフィールドのCGRectを取得し、UIScrollView's scrollRecToVisibleメソッドを呼び出す必要があると考えました。 UITextFieldDelegateメソッドを呼び出してtextFieldDidBeginEditingメソッドscrollRecToVisibleを実装しました。これは実際には、スクロールするとsnapUITextFieldが所定の位置に配置されるという奇妙な副作用がありました。長い間、私はそれが何であるかを理解できませんでした。次に、textFieldDidBeginEditing Delegateメソッドをコメントアウトしましたが、すべて機能します!!(???)。判明したように、UIScrollViewは実際に暗黙的に現在編集されているUITextFieldを暗黙的に表示可能なウィンドウに持ってくると信じています。 UITextFieldDelegateメソッドの実装とその後のscrollRecToVisibleの呼び出しは冗長であり、奇妙な副作用の原因でした。

キーボードが表示されたときにUITextFieldUIScrollViewを適切にスクロールする手順は次のとおりです。

// 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. contentSizeUIScrollViewviewDidLoadより大きく設定されていることを確認してください
  4. 縮小キーボードが存在する場合のUIScrollView
  5. 元に戻すキーボードがなくなったときのUIScrollView
  6. Ivarを使用して、キーボードが既に存在する場合でも、UITextFieldがタブ化されるたびにキーボード通知が送信されるため、キーボードが既に画面に表示されているかどうかを検出しますshrinking the UIScrollView縮小

注意すべきことの1つは、別のUIKeyboardWillShowNotificationをタブで移動すると、キーボードが既に画面上にある場合でもUITextFieldが起動することです。キーボードが既に画面上にあるときに、UIScrollViewのサイズ変更を避けるために、ivarを使用してこれを処理しました。キーボードが既にあるときにUIScrollViewのサイズを誤って変更すると、悲惨な結果になります。

このコードがあなたの一部に多くの頭痛の種を救うことを願っています。

445
Shiun

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)
265
DK_

textFieldDidBeginEdittingtextFieldDidEndEditingでは、以下のように関数[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)
    }
242
sumanthkodi

TextFieldを使うだけで:

1a)Interface Builderを使用する:すべてのTextFields => Edit => Embed In => ScrollViewを選択します。

1b)scrollViewという名前のUIScrollViewにTextFieldを手動で埋め込む

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];
}
133
DAS

ユニバーサルソリューション の場合、これは IQKeyboardManager を実装するための私のアプローチでした。

enter image description here

Step1: - シングルトンクラスにUITextFieldUITextView、およびUIKeyboardのグローバル通知を追加しました。 IQKeyboardManager と呼びます。

Step2: - UIKeyboardWillShowNotificationUITextFieldTextDidBeginEditingNotificationUITextViewTextDidBeginEditingNotificationの通知が見つかったら、UIWindow.rootViewController階層からtopMostViewControllerインスタンスを取得します。その上でUITextField/UITextViewを正しく発見するためには、topMostViewController.viewのフレームを調整する必要があります。

Step3: - 最初に回答したUITextField/UITextViewに対するtopMostViewController.viewの予想移動距離を計算しました。

Step4: - 予想される移動距離に合わせてtopMostViewController.view.frameを上下に移動しました。

Step5: - UIKeyboardWillHideNotificationUITextFieldTextDidEndEditingNotification、またはUITextViewTextDidEndEditingNotificationの通知が見つかった場合は、UIWindow.rootViewController階層からtopMostViewControllerインスタンスを取得します。

Step6: - 元の位置に戻す必要があるtopMostViewController.viewの擾乱距離を計算しました。

Step7: - 距離に応じてtopMostViewController.view.frameを元に戻しました。

Step8: - アプリロード時にシングルトンをインスタンス化します IQKeyboardManager classインスタンスなので、アプリ内のすべてのUITextField/UITextViewは予想される移動距離に応じて自動的に調整されます。

これですべてです IQKeyboardManager /を使用して、 コード行を追加しない 本当に!関連するソースファイルをプロジェクトにドラッグアンドドロップするだけです。 IQKeyboardManager もサポートしています デバイスの向き 自動UIToolbar管理 KeybkeyboardDistanceFromTextField そして、あなたが思う以上のこと。

110

私は普遍的なドロップインUIScrollViewUITableView、さらにはUICollectionViewというサブクラスをまとめました。このサブクラス内のすべてのテキストフィールドをキーボードの邪魔にならないように移動します。

キーボードが表示されようとしているとき、サブクラスは編集しようとしているサブビューを見つけ、そのビューが表示されるようにフレームとコンテンツのオフセットを調整します。キーボードが消えると、以前のサイズに戻ります。

UITableViewベースのインターフェース、または手動で配置されたビューで構成されるインターフェースのいずれかで、基本的にどのような設定でも機能するはずです。

ここがここにある: キーボードの邪魔にならないようにテキストフィールドを動かすための解決策

101
Michael Tyson

Swift /プログラマーの方へ:

これはあなたのためにすべてをするでしょう、単にあなたのView Controllerクラスにこれらを入れて、あなたのView ControllerにUITextFieldDelegateを実装し、selfにtextFieldのデリゲートを設定 

textField.delegate = self // Setting delegate of your UITextField to self

デリゲートコールバックメソッドを実装します。

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}
85
Satnam Sync

すでに多くの答えがありますが、それでも「完璧な」バグのない、後方互換性のある、ちらつきのないアニメーションに必要なすべての派手なポジショニングのものが上記の解決策にはありません。 (フレーム/境界とcontentOffsetを一緒にアニメートするときのバグ、異なるインターフェイスの向き、iPadの分割キーボードなど)
私の解決策を教えてください。 
(あなたがUIKeyboardWill(Show|Hide)Notificationを設定したと仮定します)

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = [notification userInfo];

    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];

    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];

    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);

    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;

    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any Nice visual offset between control and keyboard or control and top of the scroll view.

        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.Origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;

        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;

        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);

            // make sure we don't set an impossible offset caused by the "Nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.Origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.Origin.y;

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }

    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = notification.userInfo;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;

    [UIView commitAnimations];
}
63
Martin Ullrich

Shiun氏は、「結局のところ、UIScrollViewは暗黙的に現在編集中のUITextFieldを表示可能ウィンドウに暗黙的に表示する」と述べた。これはiOS 3.1.3には当てはまるが、3.2、4.0、または4.1には当てはまらない。 UITextFieldをiOS> = 3.2で表示するためには、明示的にscrollRectToVisibleを追加する必要がありました。

61
cbranch

考慮すべきことの1つは、あなたがUITextFieldを単独で使いたいかどうかです。 UITextFieldsの外でUITableViewCellsを実際に使用している、うまく設計されたiPhoneアプリケーションに出会ったことはありません。

余分な作業になりますが、すべてのデータ入力ビューとテーブルビューを実装することをお勧めします。 UITextViewUITableViewCellsに追加してください。

46

これ はこの問題の解決策を詳しく述べたものです。 「キーボードの下にあるコンテンツの移動」の下にあるソースコードを見てください。それはかなり簡単です。

編集:例には週の不調があることに気づいた。あなたはおそらくUIKeyboardWillHideNotificationの代わりにUIKeyboardDidHideNotificationを聴きたくなるでしょう。それ以外の場合は、キーボードを閉じるアニメーションの間、キーボードの後ろにあるスクロールビューが切り取られます。

45
Mihai Damian

最も簡単な解決策が見つかりました  

- (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 = 80; // Tweak as needed
    const float movementDuration = 0.3f; // Tweak as needed

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

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

多くのUITextFieldに有効な小さな修正

#pragma mark UIKeyboard handling

#define kMin 150

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
   if (currTextField) {
      [currTextField release];
   }
   currTextField = [sender retain];
   //move the main view, so that the keyboard does not hide it.
   if (self.view.frame.Origin.y + currTextField.frame.Origin. y >= kMin) {
        [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 = kMin - currTextField.frame.Origin.y ;
   }
   else
   {
      // revert back to the normal state.
      rect.Origin.y = 0;
   }
   self.view.frame = rect;

   [UIView commitAnimations];
}


- (void)keyboardWillShow:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately

   if ([currTextField isFirstResponder] && currTextField.frame.Origin.y + self.view.frame.Origin.y >= kMin)
   {
      [self setViewMovedUp:YES];
   }
   else if (![currTextField isFirstResponder] && currTextField.frame.Origin.y  + self.view.frame.Origin.y < kMin)
   {
      [self setViewMovedUp:NO];
   }
}

- (void)keyboardWillHide:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
   if (self.view.frame.Origin.y < 0 ) {
      [self setViewMovedUp:NO];
   }

}


- (void)viewWillAppear:(BOOL)animated
{
   // register for keyboard notifications
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) 
                                                name:UIKeyboardWillShowNotification object:self.view.window]; 
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) 
                                                name:UIKeyboardWillHideNotification object:self.view.window]; 
}

- (void)viewWillDisappear:(BOOL)animated
{
   // unregister for keyboard notifications while not visible.
   [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 
}
31
tt.Kilew

RPDPのコードは、テキストフィールドをキーボードの邪魔にならない場所に移動しました。しかし、キーボードを使用して却下した後に上部にスクロールすると、上部はビューの外側にスクロールアップされています。これはシミュレータとデバイスに当てはまります。そのビューの上部にあるコンテンツを読むには、ビューをリロードする必要があります。

彼の次のコードは、見解を元に戻すことになっていませんか?

else
{
    // revert back to the normal state.
    rect.Origin.y += kOFFSET_FOR_KEYBOARD;
    rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
29
Steve

UIScrollViewのサイズを変更して、ビューを上に移動することが正しいアプローチであるかどうかわかりません。 article について少し詳しく説明しました

23
Jose Muanis

元のビューステートに戻すには、以下を追加します。

-(void)textFieldDidEndEditing:(UITextField *)sender

{
    //move the main view, so that the keyboard does not hide it.
    if  (self.view.frame.Origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}
21

非常に多くの解決策がありますが、私はそれがうまくいくまでに数時間を費やしました。それで、私はここにこのコードを入れました(ただプロジェクトに貼り付けてください、どんな修正も必要としません):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

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

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

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

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.Origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.Origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    activeField = nil;
}

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

S:誰かがすぐに望みの効果を生み出すのを手助けするコードがあるといいのですが。 (Xcode 4.5)

19
HotJard

@ user271753

元の表示に戻すには

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
   [textField resignFirstResponder];
   [self setViewMovedUp:NO];
   return YES;
}
18
user436179

この短いトリックを試してください。

- (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 = textField.frame.Origin.y / 2; // Tweak as needed
    const float movementDuration = 0.3f; // Tweak as needed

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

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

ビューフレームを移動できるようにするには、スクロールビューは必要ありません。 viewcontroller'sビューのフレームを変更して、ビュー全体がキーボードの上に最初の応答テキストフィールドを配置するのに十分なだけ上に移動するようにすることができます。この問題に遭遇したとき、これを行うUIViewControllerのサブクラスを作成しました。キーボードが通知を表示し、ファーストレスポンダのサブビューを見つけ、(必要に応じて)メインビューを上方向にアニメートして、ファーストレスポンダがキーボードの上にくるようにします。キーボードが非表示になると、ビューは元の位置に戻ります。

このサブクラスを使用するには、カスタムView Controllerを GMKeyboardVC のサブクラスにして、この機能を継承します(viewWillAppearviewWillDisappearを実装する場合は、必ずsuperを呼び出す必要があります)。クラスは github です。

16
progrmr

Swift 4

簡単に上下に移動できますUITextFieldまたはUIView With UIKeyBoard With Animation- enter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.Origin.y - curFrame.Origin.y
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.Origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}
14
ZAFAR007

IOS 3.0以降、 docs のように、テキストフィールドのインライン編集が行われると、UITableViewControllerクラスは自動的にそのテーブルビューのサイズを変更して再配置します。私が思うに、テキストフィールドをUITableViewCellの中に入れるだけでは十分ではないと思います。

ドキュメントから

Table View ControllerはTable View行のインライン編集をサポートします;たとえば、編集モードで行が埋め込みテキストフィールドを持つ場合、編集中の行を仮想キーボードの上にスクロールします。 ____。]が表示されます。

12
Dheeraj V.S.

これは私が特定のレイアウトのために思いついたハックの解決策です。このソリューションは、セクションをスクロールして表示するという点でMatt Gallagherソリューションと似ています。私はまだiPhoneの開発に慣れていないので、レイアウトがどのように機能するのかについて慣れていません。したがって、このハック。

私の実装では、フィールド内をクリックするときのスクロールと、ユーザーがキーボードで次に選択するときのスクロールをサポートする必要がありました。

私は775の高さのUIViewを持っていました。コントロールは広いスペースの上に3のグループに基本的に広げられます。私は次のようなIBレイアウトになった。

UIView -> UIScrollView -> [UI Components]

これがハックです

UIScrollViewの高さを実際のレイアウト(1250)より500単位大きく設定しました。次に、スクロールする必要がある絶対位置と、IBタグ番号に基づいてそれらを取得するための単純な関数を含む配列を作成しました。

static NSInteger stepRange[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};

NSInteger getScrollPos(NSInteger i) {
    if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
        return 0 ;
    return stepRange[i] ;
}

TextFieldDidBeginEditingとtextFieldShouldReturnに次の2行のコードを使用するだけです(次のフィールドナビゲーションを作成する場合は後者)。

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;

例。

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
    [self.scrollView setContentOffset:point animated:YES] ;
}


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

    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];

    if (nextResponder) {
        [nextResponder becomeFirstResponder];
        CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
        [self.scrollView setContentOffset:point animated:YES] ;
    }
    else{
        [textField resignFirstResponder];
    }

    return YES ;
}

このメソッドは、他のメソッドのように 'スクロールバック'しません。これは必要条件ではありませんでした。これもかなり「背の高い」UIViewのためのもので、私は内部レイアウトエンジンを学ぶ日がありませんでした。

12
Steve McFarlin

ここで私はキーパッドを扱うための最も簡単な解決策を見つけました。

サンプルコードの下にコピーアンドペーストして、テキストフィールドまたは上に移動したいビューを変更するだけです。

ステップ1 

あなたのコントローラーの2つの方法の下でちょうどコピーアンドペースト

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void)deregisterFromKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

ステップ2 

キーパッド通知をそれぞれviewWillAppearおよび viewWillDisappearメソッドに登録し、登録解除します。

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

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

ステップ-3 

ここで魂の部分が来る、ちょうどあなたのテキストフィールドを交換して、あなたがどのくらい上方に動かしたいかの高さを変える。

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

    //you need replace your textfield instance here
    CGPoint textFieldOrigin = self.tokenForPlaceField.frame.Origin;
    CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;

    CGRect visibleRect = self.view.frame;
    visibleRect.size.height -= currentKeyboardSize.height;

    if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
    {
        //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below

        CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height  + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification *)notification
{
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

Reference:さて、 この男に感謝します 、この美しいコードスニップを共有した、きれいな解決策.

これが誰かにとって非常に有用なものになることを願っています。

11
swiftBoy

主題に関する初心者のための良いチュートリアルを探していて、最高のチュートリアル ここ を見つけました。

チュートリアルの下部にあるMIScrollView.hの例では、必ずスペースを

@property (nonatomic, retain) id backgroundTapDelegate;

お分かりのように.

10
savagenoob

UITextFieldUITableViewCell内にある場合は、スクロールは自動的に設定されます。

そうでない場合は、おそらくテーブルビューの不適切なコード/設定が原因です。

例えば、以下のように一番下に1つのUITextFieldを付けて私の長いテーブルをリロードすると、 

-(void) viewWillAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

それから下部の私のテキストフィールドは、私がテキストフィールドの内側をクリックしたときに現れたキーボードによって隠されていました。

これを直すために私はこれをしなければならなかった -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}
10

あなたが一行も書く必要がないこの第三者を使う

https://github.com/hackiftekhar/IQKeyboardManager

プロジェクトをダウンロードし、プロジェクトにIQKeyboardManagerをドラッグアンドドロップします。問題がある場合は、README文書を参照してください。

みんな本当にキーボードを管理するためにその頭痛を取り除きます..

ありがとう、そして頑張ってください!

9
Arvind Kumar

:この答えはあなたのtextFieldがscrollViewにあると仮定しています。

私は自分のビューのフレームを台無しにするのではなく、scrollContentInsetとscrollContentOffsetを使用してこれを処理することを好みます。

最初にキーボード通知を聞きましょう 

//call this from viewWillAppear
-(void)addKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
    [[NSNotificationCenter default
    Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

次のステップは、現在の最初のレスポンダを表すプロパティを保持することです(現在UITextfield/UITextVIewにはキーボードがあります)。

このプロパティを設定するためにデリゲートメソッドを使います。他のコンポーネントを使用している場合は、似たようなものが必要になります。

Textfieldの場合はdidBeginEditingに、textViewの場合はshouldBeginEditingに設定します。これは、textViewDidBeginEditingが何らかの理由でUIKeyboardWillShowNotificationの後に呼び出されるためです。 

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
    self.currentFirstResponder = textView;
    return YES;
}

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

最後に、これが魔法です

- (void)keyboardWillShow:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];


    /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
    if(self.currentFirstResponder){

        //keyboard Origin in currentFirstResponderFrame
        CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.Origin fromView:nil];

        float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);

        //only scroll the scrollview if keyboard overlays the first responder
        if(spaceBetweenFirstResponderAndKeyboard>0){
            //if i call setContentOffset:animate:YES it behaves differently, not sure why
            [UIView animateWithDuration:0.25 animations:^{
                [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
            }];
        }
    }

    //set bottom inset to the keyboard height so you can still scroll the whole content

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;

}

- (void)keyboardWillHide:(NSNotification*)aNotification{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}
8
Juraj Petrik

これはSwiftを使った解決策です。

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;

        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your app might not need or want this behavior.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.Origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}
8
Homam

あなたは特定のフレームサイズでプログラム的にスクロールビューを追加する必要があります。 UIScrollViewDelegateを.hファイルに追加する必要があります。 viewDidLoad()で以下のように書く必要があるため、scrollviewを有効にする必要があります。

scrollview.scrollEnabled=YES;
scrollview.delegate=self;

scrollview.frame = CGRectMake(x,y,width,height);
//---set the content size of the scroll view--- 

[scrollview setContentSize:CGSizeMake(height,width)];

このようにして、あなたはあなたのx、y、幅と高さの値を追加することができます。

7
deepti

これを試して:

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:self.m_Sp_Contact])
    {
        [self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES];          
    }
}
7
user1105624

Swift 2.0:

UIScrollViewを追加し、その上にtextFieldsを追加します。ストーリーボードからVCへの参照を作成します。

@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var scrollView: UIScrollView!

これらのメソッドを追加します:UITextFieldDelegateおよびUIScrollViewDelegate。

//MARK:- TEXTFIELD METHODS
    func textFieldShouldReturn(textField: UITextField) -> Bool {

        if(username.returnKeyType == UIReturnKeyType.Default) {
            password.becomeFirstResponder()
        }
        textField.resignFirstResponder()
        return true
    }
    func textFieldDidBeginEditing(textField: UITextField) {

        dispatch_async(dispatch_get_main_queue()) {

            let scrollPoint:CGPoint = CGPointMake(0,textField.frame.Origin.y/4)
            self.scrollView!.setContentOffset(scrollPoint, animated: true);
        }
    }
    func textFieldShouldEndEditing(textField: UITextField) -> Bool {

        dispatch_async(dispatch_get_main_queue()) {
          UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) })
        }
        return true
    }
    override func touchesBegan(touches: Set<UITouch>,
        withEvent event: UIEvent?) {
            self.view.endEditing(true)
    }
    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.scrollView.scrollEnabled =  true

        dispatch_async(dispatch_get_main_queue()) {
            UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true)

            })
        }
    }
7
A.G

これはキーボード操作のための無料のライブラリです iPhoneアプリケーションのキーボード操作 。 1行のコードを書く必要があります。

[AutoScroller addAutoScrollTo:scrollView];

これは、フォームでキーボードを扱うのに最適です。

6
user966931

Swiftを使用している場合は、最善の方法はプロトコル指向プログラミングを使用することです。

まず最初にKeyboardCapableプロトコルを作成しなければなりません。それはそれに適合するすべてのUIViewControllerにキーボードオブザーバを登録および登録解除する能力を与えます:

import Foundation
import UIKit

protocol KeyboardCapable: KeyboardAnimatable {
    func keyboardWillShow(notification: NSNotification)
    func keyboardWillHide(notification: NSNotification)
}

extension KeyboardCapable where Self: UIViewController {
    func registerKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }
}

上記のコードに無関係なKeyboardAnimatableキーワードがあります。それは私たちが作成する必要がある次のプロトコルの名前です。

import Foundation
import UIKit

protocol KeyboardAnimatable {

}

extension KeyboardAnimatable where Self: UIViewController {
    func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.Origin.x, -height, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }

    func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.Origin.x, 0.0, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }
}

このKeyboardAnimatableプロトコルは、それに準拠するすべてのUIViewControllerに、それぞれビュー全体を上下にアニメーション化する2つのメソッドを与えます。

KeyboardCapableKeyboardAnimatableに準拠していれば、すべてのUIViewControllerがKeyboardCapableに準拠していて、KeyboardAnimatableにも準拠しています。カッコいい。

UIViewControllerKeyboardCapableに準拠し、キーボードイベントに反応するのを見てみましょう:

import Foundation
import UIKit

class TransferConfirmViewController: UIViewController, KeyboardCapable {
    //MARK: - LIFE CYCLE       
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        registerKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        unregisterKeyboardNotifications()
    }

    //MARK: - NOTIFICATIONS
    //MARK: Keyboard
    func keyboardWillShow(notification: NSNotification) {
        let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration)
    }

    func keyboardWillHide(notification: NSNotification) {
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardHideFullViewAnimation(withDuration: animationDuration)
    }
}

これであなたのUIViewControllerはキーボードイベントに反応し、結果としてアニメーション化します。

注:ビューをプッシュまたはプルする代わりにカスタムアニメーションが必要な場合は、KeyboardAnimatableプロトコルでカスタムメソッドを定義するか、KeyboardCapable関数でそれらを実行する必要があります。それはあなた次第です。

6
Jorge Ramos

もっとずっと洗練された解決策はUIViewサブクラスを使って(これは必ずしも適切ではありませんが)親のフレーム変更時にすべてのサブビューを再計算することです(そして賢いこと:新しいフレームサイズが変わったら再計算するだけです、 CGRectEqualToRectをオーバーライドして[super setFrame:frame_]を呼び出す前に新しいフレームを比較するためのsetFrame。これに対する唯一のキャッチは、あなたが使用しようとしているUIViewControllerがおそらくキーボードイベントをリスンすべきであるということです(あるいは、便利なカプセル化のためにUIViewそれ自身の中でそれをすることができます)。しかしUIKeyboardWillShowNotificationUIKeyboardWillHideNotificationだけです。これはまさに滑らかに見えるようにするためです(CGがそれを呼び出すのを待っているなら、あなたはぎっしりの瞬間を得るでしょう)。

とにかく、これには正しいことをするUIViewサブクラスを構築するという利点があります。

単純な実装はdrawRect:(don't)をオーバーライドすることでしょう、より良いのは単にlayoutSubviewsを使用することです(そしてそれからUIViewControllerの中で、またはshowまたはshowのために呼び出されるSINGLEメソッドで[view setNeedsLayout]を呼び出すことができません。隠す)。

この解決法はキーボードのオフセットのハードコーディング(分割されていない場合などに変更されます)を避けることができ、またあなたのビューが他の多くのビューのサブビューであり、それでも正しく反応することを意味します。

他に解決策がない限り、そのようなものをハードコーディングしないでください。あなたが正しいことをしていれば、OSはあなたに(あなたの新しいframeサイズに基づいて)知的に再描画する必要があるだけの十分な情報を提供します。これはずっときれいで、あなたのやり方です すべき 物事をやる。 (ただし、もっと良い方法があるかもしれません。)

乾杯。

5
Matt Weaver

次のコードをクラスに入れて、必要に応じてカスタマイズするだけです。

-(void)textFieldDidBeginEditing:(UITextField *)textField {
     //Show Keyboard
     self.view.frame = CGRectMake(self.view.frame.Origin.x,
                              self.view.frame.Origin.y-50,
                              self.view.frame.size.width,
                              self.view.frame.size.height);   
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
     // Hide keyboard
     self.view.frame = CGRectMake(self.view.frame.Origin.x,
                              self.view.frame.Origin.y+50,
                              self.view.frame.size.width,
                              self.view.frame.size.height); 
}

Textfieldデリゲートメソッドを使ってもできます。以下のコードを確認してください。スクロールビューにテキストフィールドを配置したときに私には役に立ちます。

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
     if(textField == answer)
    {   
         CGPoint cPoint = textField.frame.Origin;
         [scrollView setContentOffset:CGPointMake(0, cPoint.y - 100) animated:YES];
    }
}

注: あなたはあなたの見解に従ってcPoint.y - 100の値を変更する必要があります。

4
Ganesh Guturi

これが私のautolayoutを使ったバージョンです。

これは、テキストフィールド/テキストビューを含むビューをUIScrollViewに埋め込んで、下からスーパービューへの制約を設定し、アウトレットを作成し、通知を使用してキーボードの高さに応じて定数を更新することです。 Appleの例 here 、およびAutoLayoutを使用したUIScrollViewに関するAppleテクニカルノート here

1)ビューVをUIScrollView Sに埋め込む:すでに定数とサブビューを設定している場合は、ビューとサブビューをViewControllerのビューにコピー/貼り付けしてから、[エディタ] - > [埋め込み]メニューを使用しますコピーしたビューを最後に削除します。

2)以下の制約を設定してください。

  • Sから上へレイアウトガイド:0
  • 一番下のレイアウトガイドへのS:0
  • スーパービューにつながるS:0
  • スーパービューに続くS:0

  • スーパービューへのVトップスペース:0

  • スーパービューへのV下部スペース:0
  • スーパービューへのV末尾スペース:0
  • スーパービューへのV先導スペース:0

  • Sと同じ幅のV

  • スーパービューへの最新の下Vサブビュー:20

3)最新の制約からView Controllerへのアウトレットを作成します

4)以下のコードを使用してください。

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpaceToContentView;

// ...

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    // ...

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

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

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Handle keyboard

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    self.bottomSpaceToContentView.constant = kBottomMargin + kbSize.height;
    [self.view layoutIfNeeded];
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    self.bottomSpaceToContentView.constant = kBottomMargin;
    [self.view layoutIfNeeded];
}

そしてtadaaaaa、それは機能します!

4
dulgan

アプローチを伝えるために利用可能な多くの答えがあります。私は同じアプローチを取りましたが、実装は良くありません。

これが 基本のアイデア です。 keyboardWasShownメソッドを修正しました。

{
// Obtain keyboard Info
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

// Obtain ScrollView Info w.r.t. top View
CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil];

// Depending upon your screen Ui, Scroll View's bottom Edge might be at some offset from screen's bottom
// Calculate the exact offset
int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.Origin.y + scrollViewRect.size.height);
int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset;


// We may also need to consider the Insets if already present with ScrollView. Let's keep it simple for now
// But we should store these, so that we can restore the Insets when Keyboard is gone
// origInsets = self.scrollView.contentInset;

// Set the new Insets for ScrollView
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

// Visible frame (not overlapped by Keyboard)
CGRect visibleFrame = self.view.frame;
visibleFrame.size.height -= keyboardRect.size.height;

// Get the Rect for Textfield w.r.t self.view
CGRect activeFieldFrame = self.activeField.frame;
activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView];

// Check if the TextField is Visible or not
if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) {
    // Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View
    [self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}

}

そしてこのメ​​ソッドを追加してactiveFieldを初期化します。

- (IBAction)textFieldDidBeginEditing:(UITextField *)sender
{
self.activeField = sender;
}
4
vinksharma

これはデバイスから独立したオフセット計算です。キーボードとテキストフィールドの重なりの高さを取得します。

func keyboardShown(notification: NSNotification) {
    let info  = notification.userInfo!
    let value: AnyObject = info[UIKeyboardFrameEndUserInfoKey]!

    let rawFrame = value.CGRectValue
    let keyboardFrame = view.convertRect(rawFrame, fromView: nil)

    let screenHeight = UIScreen.mainScreen().bounds.size.height;
    let Ylimit = screenHeight - keyboardFrame.size.height
    let textboxOriginInSuperview:CGPoint = self.view.convertPoint(CGPointZero, fromCoordinateSpace: lastTextField!)

    self.keyboardHeight = (textboxOriginInSuperview.y+self.lastTextField!.frame.size.height) - Ylimit

    if(self.keyboardHeight>0){
        self.animateViewMoving(true, moveValue: keyboardHeight!)
    }else{
        keyboardHeight=0
    }
}

keyBoardHeightはオフセットです。

https://github.com/michaeltyson/TPKeyboardAvoiding このファイルをダウンロードしてテーブルビューにカスタムクラスを追加すると、すべてのことを管理できます。それはあなたが他のためにそれをチェックアウトすることができます多くのオプションがあります、これはあなたがキーボードを避けるために必要なすべてです

4
anand madhav

これは私が作ったUITextfield(および他の同様のフィールド)カテゴリです。これはtextfieldがキーボードを避けるようにするでしょう、あなたはこれをあなたのView Controllerにそのまま落とすことができなければなりません、そしてそれは動作するはずです。現在のテキストフィールドがアニメーションのあるキーボードの上にあるように画面全体を上に移動します

#import "UIView+avoidKeyboard.h"
#import "AppDelegate.h"

@implementation UIView (avoidKeyboard)

- (void) becomeFirstResponder {

if(self.isFirstResponder)
    return;

[super becomeFirstResponder];

if ([self isKindOfClass:[UISearchBar class]] ||
    [self isKindOfClass:[UITextField class]] ||
    [self isKindOfClass:[UITextView class]])
{
    AppDelegate *appDelegate    = [UIApplication sharedApplication].delegate;

    CGRect screenBounds         = appDelegate.window.frame;

    CGFloat keyboardHeight;
    CGFloat keyboardY;
    CGFloat viewsLowestY;
    CGPoint Origin              = [self.superview convertPoint:self.frame.Origin toView:appDelegate.window]; //get this views Origin in terms of the main screens bounds

    if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ //the window.frame doesnt take its orientation into account so if its sideways we must use the x value of the Origin instead of the y
        keyboardHeight          = 216;
        keyboardY               = screenBounds.size.height  - keyboardHeight; //find the keyboards y coord relative to how much the main window has moved up
        viewsLowestY            = Origin.y + self.frame.size.height; //find the lowest point of this view
    }
    else {
        keyboardHeight          = 162;
        keyboardY               = screenBounds.size.width  - keyboardHeight;
        viewsLowestY            = Origin.x + self.frame.size.height;
    }

    CGFloat difference          = viewsLowestY - keyboardY + 20; //find if this view overlaps with the keyboard with some padding

    if (difference > 0){ //move screen up if there is an overlap

        [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{

            CGRect frame = appDelegate.window.frame;

            if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){
                frame.Origin.y -= difference;
            }
            else {
                frame.Origin.x -= difference;
            }
            appDelegate.window.frame = frame;
        }
        completion:nil];
    }
}
}

//look at appDelegate to see when the keyboard is hidden

@end

あなたのappDelegateでこの関数を追加してください

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHides:) name:UIKeyboardWillHideNotification object:nil]; //add in didFinishLaunchingWithOptions

...

- (void)keyboardHides:(NSNotification *)notification
{
    [UIView animateWithDuration:0.3 animations:^{
        [window setFrame: CGRectMake(0, 0, window.frame.size.width, window.frame.size.height)];
    } completion:nil];
}
4
Fonix

次の手順に従ってください。 

1).hファイルに次の変数を宣言します。

  {      
         CGFloat animatedDistance;
  }

2).mファイルに次の定数を宣言します。

  static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
  static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
  static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
  static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
  static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;

3)UITextFieldデリゲートを使用してキーボードを上下に移動します。

  -(void) textFieldDidBeginEditing:(UITextField *)textField
  { 
         if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
         {
               CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
               CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];

               CGFloat midline = textFieldRect.Origin.y + 0.5 * textFieldRect.size.height;
               CGFloat numerator =
    midline - viewRect.Origin.y
    - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
               CGFloat denominator =
    (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
    * viewRect.size.height;
               CGFloat heightFraction = numerator / denominator;

               if (heightFraction < 0.0)
               {
                     heightFraction = 0.0;
               }
               else if (heightFraction > 1.0)
               {
                     heightFraction = 1.0;
               }

               UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
               if (orientation == UIInterfaceOrientationPortrait)
               {
                     animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
               }
               else
               {
                     animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
               }

               CGRect viewFrame = self.view.frame;
               viewFrame.Origin.y -= animatedDistance;

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

               [self.view setFrame:viewFrame];

               [UIView commitAnimations];
       }
  }

  -(void) textFieldDidEndEditing:(UITextField *)textField
  {
       if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
       {
             CGRect viewFrame = self.view.frame;
             viewFrame.Origin.y += animatedDistance;

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

             [self.view setFrame:viewFrame];

             [UIView commitAnimations];
       }
 }
3

私はすべてを1つのクラスに包みます。あなたのviewcontrollerがロードされたときにこれらのコード行を呼び出すだけです:

- (void)viewDidLoad {
    [super viewDidLoad];
    KeyboardInsetScrollView *injectView = [[KeyboardInsetScrollView alloc] init];
    [injectView injectToView:self.view withRootView:self.view];
}

これがサンプルプロジェクトのリンクです。
https://github.com/caohuuloc/KeyboardInsetScrollView

3
Cao Huu Loc

私は最近、メッセージングアプリで作業しているときにも同じような状況に陥っていました。私はキーボードの上にこだわるカスタムUIViewを作成し、あなたが自動的に必要なことのほとんどをする

MessageComposerView

http://www.thegameengine.org/wp-content/uploads/2013/11/message_composer_quad_1.jpg

このプロジェクトの背後にあるアイデアは、iMessageコンポジションビューAKAと同様に機能するものを作成することでした。

  • キーボードを閉じると、キーボードの上部に固定され、画面の下部に移動します。
  • テキストの変更を処理します
  • 回転を処理する

UIScrollViewのサイズを変更したり再設定したりするには、次のオプションのデリゲートメソッドを使用します。

- (void)messageComposerFrameDidChange:(CGRect)frame withAnimationDuration:(float)duration;

フレームが変更された(サイズ変更、位置変更、回転)たびに呼び出され、アニメーションの長さも提供します。この情報を使用して、必要に応じてUIScrollViewのフレームとコンテンツのインセットのサイズを変更できます。

3
alexgophermix

これをポッドファイルに追加してください - > pod 'IQKeyboardManager'

それは、キーボード、スクロールビュー、その他すべてを処理することです。

あなたは何かをコーディングする必要はありません、より良い解決策を見つけることができませんでした!

テキストフィールドの表示、画面移動、複数のテキストフィールドがある場合は前後の矢印を処理する拡張機能があります。

また、削除できるカスタムの[完了]ボタンもあります。

リンク - > https://github.com/hackiftekhar/IQKeyboardManager

3
Kakshil Shah

これが最善の解決策であることがわかりました。下記のコードに従ってください。 

以下をVertical Space - Bottom Layout Guide - TextField制約に付けてください。 

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;

次に、キーボード通知用のオブザーバを追加します。

- (void)observeKeyboard {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

これをviewDidLoadに追加してください 

[self observeKeyboard]; 

最後にキーボードの変更を処理するメソッド。

- (void)keyboardWillShow:(NSNotification *)notification {
//THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS.
kbHeight = 0;
height = 0;
self.textViewBottomConst.constant = height;
self.btnViewBottomConst.constant = height;

    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];

    CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];

    int kbHeight = finalKeyboardFrame.size.height;

    int height = kbHeight + self.textViewBottomConst.constant;

    self.textViewBottomConst.constant = height;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}

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

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    self.textViewBottomConst.constant = 10;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}
3
Manesh

Appleのように、はるかにシンプルでありながら一般化された方法では、キーパッドの高さを考慮します。これは、キーボードの上にカスタムツールバーを使用する場合に非常に役立ちます。 Appleのアプローチ こちら にはほとんど問題がありません。

これが私のアプローチです(Appleのやり方を少し変更しました)-

// 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.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}

// UIKeyboardWillHideNotification
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}
3
Sam92

私はこれが遅すぎることを知っています、しかし私はそれをする私のやり方、特に将来の訪問者と共有したいと思いました。多くの良い方法が共有されていましたが、私はUIが完全に悪くなるのが好きではありませんでした。二つの部分を含む簡単な方法があります: -

  1. TextFieldを編集中にキーボードの上に浮かせたいものがあれば、それらをビューの子になるようにビューに追加します。そして外観を維持し、UIに悪影響を与えないようにするのは簡単です。
  2. 作成したビューをキーボードの上に移動するには、素晴らしいツール CGAffineTransform(TranslationX: x, TranslationY: y) を使用してください。  

私はそれが非常に単純に見えることを知っていますが、それは本当に効果的できちんとしています。 enter image description here

3
Badr

UIViewControllerを拡張する簡単なソリューション

https://github.com/damienromito/VisibleFormViewController

enter image description here

3
Damien Romito

簡単な解決策と最新のアニメーションAPI。 Origin.yを215に変更すると、どちらの値でもうまくいくようにカスタマイズできます。

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (self.view.frame.Origin.y >= 0) {

        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-215, self.view.frame.size.width, self.view.frame.size.height);
       }];
   }
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    if (self.view.frame.Origin.y < 0) {
        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+215, self.view.frame.size.width, self.view.frame.size.height);
        }];

    }
}
2
Vidhur

@sumanthkodiの答えを広げたいと思います。

一部の人々が述べているように、 constraint を使用しているとUIViewは動きませんので、彼のアプローチは新しい実装では機能しません。

私は次のようにコードを編集し(そしてSwift 2.0に移植し)、それが何人かの人々に役立つことを願っています:


1)上に移動したいビューの垂直方向の拘束を参照します。

@IBOutlet var viewConstraint: NSLayoutConstraint!

ストーリーボードのこのvarを必ず制約付きで参照してください。

2)デリゲートを追加してリスナーを実装します。これは以前と同じ実装です。

class YourViewController: UIViewController, UITextFieldDelegate {

    ...

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

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

    ...

}

3)アニメーションメソッドanimateTextFieldYourViewControllerクラスに追加します。必要に応じて一時制約値を設定してください。

func animateTextField(textfield: UITextField, up: Bool) {

    let originalConstraint = 50
    let temporaryConstraint = 0
    let movementDuration = 0.3

    let constraint = CGFloat(up ? temporaryConstraint : originalConstraint)

    containerViewConstraint.constant = constraint
    UIView.animateWithDuration(movementDuration) {
        self.view.layoutIfNeeded()
    }

}
2
andreas

これは完璧に動作します。スクロールビューはテキストフィールドの位置によって大気的に調整します。

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.25;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
@interface LoginVC ()
{
  CGFloat animatedDistance;
   CGRect viewFrameKey;
}

 //In ViewDidLoad
   viewFrameKey=self.view.frame;



- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =
[self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.Origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.Origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
    heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
    heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
    orientation == UIInterfaceOrientationPortraitUpsideDown)
{
    animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
    animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.Origin.y -= animatedDistance;

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

[self.view setFrame:viewFrame];

[UIView commitAnimations];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrameKey];
[UIView commitAnimations];
}
2
Mahesh reddy

このクラスが見つかりました:

https://github.com/OliverLetterer/SLScrollViewKeyboardSupport

これまでのところ、アニメーションと正しいオフセットを含めて、iPhone上で非常にうまく機能しています。

それを使用するには、単にviewDidLoadに追加します。

self.support = [[SLScrollViewKeyboardSupport alloc] initWithScrollView:self.scrollView];
2
Sebastian Roth

非常に軽量な解決策は KeyboardAnimator を使うことです。 

プロジェクトはサンプル実装を手に入れました、ドキュメンテーションはまだ進行中です...

適切な使い方:: これはUITextFieldとUITextViewのための特定の実装を持っています

制限事項:: 完全に目的語-cになっています、Swift版は近日中に公開予定です。

2
Ratul Sharker

このコードは、キーボードの高さとテキストフィールドの奥行きに基づいて、どれだけ上に移動する必要があるかを計算します。忘れずにデリゲートを追加し、ヘッダーにUITextFieldDelegateを継承してください。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [_tbxUsername resignFirstResponder];
    [_tbxPassword resignFirstResponder];
}

- (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
{
    int animatedDistance;
    int moveUpValue = textField.frame.Origin.y+ textField.frame.size.height;
    UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {

        animatedDistance = 236-(460-moveUpValue-5);
    }
    else
    {
        animatedDistance = 182-(320-moveUpValue-5);
    }

    if(animatedDistance>0)
    {
        const int movementDistance = animatedDistance;
        const float movementDuration = 0.3f;
        int movement = (up ? -movementDistance : movementDistance);
        [UIView beginAnimations: nil context: nil];
        [UIView setAnimationBeginsFromCurrentState: YES];
        [UIView setAnimationDuration: movementDuration];
        self.view.frame = CGRectOffset(self.view.frame, 0, movement);
        [UIView commitAnimations];
    }
}

ViewDidLoadに追加するデリゲート

_tbxUsername.delegate = self;
_tbxPassword.delegate = self;
2
teapeng
  1. TPKeyBoardAvoidingをダウンロードこのリンクから: https://github.com/michaeltyson/TPKeyboardAvoiding 。 
  2. Zipフォルダを展開してTPKeyboardAvoidingフォルダを見つけます。
  3. すべての.hファイルと.mファイルを選択してプロジェクトにドロップします。必要に応じて項目をコピーするにチェックマークが付いていることを確認してください。
  4. UIScrollViewをStoryBoardにドラッグアンドドロップしてTPKeyboardAvoidingScrollViewに関連付けます。
  5. これで、スクロールビューの上部にUI要素を追加できます。このクラスはscrollViewをドラッグした後もUI要素が接触したことを検出します。

あなたのViewController上で:

@IBOutlet weak var usernameTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var loginScrollView: UIScrollView!


override func viewWillAppear(animated: Bool) {
        loginScrollView.scrollEnabled =  false
    }

TextFieldデリゲートを追加します。

//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool
{
    if (usernameTextfield.resignFirstResponder())
    {
        passwordTextfield.becomeFirstResponder()
    }
    textField.resignFirstResponder();
    loginScrollView!.setContentOffset(CGPoint.zero, animated: true);
    loginScrollView.scrollEnabled =  false
    return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
    loginScrollView.scrollEnabled =  true

    if (textField.tag  == 1 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.4);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);

    }
    else if (textField.tag  == 2 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.0);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);
    }
}
func textFieldDidEndEditing(textField: UITextField)
{
    loginScrollView!.setContentOffset(CGPointZero,animated: true);
}
2
A.G

Scrollviewをビューに設定  

  - (void)textFieldDidBeginEditing:(UITextField *)textField
    {
     CGPoint point;
    if(textField == txtEmail){
      // -90 is for my you can change as per your postion
      point = CGPointMake(0, textField.frame.Origin.y - 90);
    }
    else if (textField == txtContact){
      point = CGPointMake(0, textField.frame.Origin.y - 90);
    }
      [scrollV setContentOffset:point animated:YES];
    }
2
seggy

IPadでスクロールアップするには、テキストフィールドのデリゲートメソッドにこれらの行を追加してください。 

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeTextfield = textField;

    CGPoint pt;
    CGRect rc = [textField bounds];
    rc = [textField convertRect:rc toView:scrlView];
    pt = rc.Origin;
    pt.x = 0;
    pt.y -= 100;

    [scrlView setContentOffset:pt animated:YES];

    scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.Origin.y+button.frame.size.height + 8 + 370);
}
2
jayesh mardiya

IQKeyboardライブラリを試してください。

これは自動的にテキストフィールドを上に移動します。

2
User511

これは、制約を使用して以下のコード行で簡単に達成できます

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]];
}

- (void)viewDidDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewDidDisappear:animated];
}

- (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info {
    CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat height = keyboardFrame.size.height;
    self.constraintToAdjust.constant = height;        UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
    UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState;
    if (animationCurve == UIViewAnimationCurveEaseIn) {
        animationOptions |= UIViewAnimationOptionCurveEaseIn;
    }
    else if (animationCurve == UIViewAnimationCurveEaseInOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseInOut;
    }
    else if (animationCurve == UIViewAnimationCurveEaseOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseOut;
    }
    else if (animationCurve == UIViewAnimationCurveLinear) {
        animationOptions |= UIViewAnimationOptionCurveLinear;
    }
    [UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{
        [self.view layoutIfNeeded];
    }                completion:nil];
}
2
Rajesh
  • テキストフィールドが完全にまたは部分的に隠れていない場合は、何も変更しないでください。
  • 隠れている正確な交差領域(キーボードの枠とテキストフィールドの枠)を計算してから、ビューの枠を変更する必要があります。

  • ここで私は完全な例を挙げています。

    3つの変数を宣言する

#define PADDING 10

@interface PKViewController ()
      @property (nonatomic, assign) CGRect originalViewFrame; //original view's frame
      @property (nonatomic, strong) UITextField *activeTextField; // current text field
      @property (nonatomic, assign) CGRect keyBoardRect; // covered area by keaboard
     @end

オリジナルフレームを保存

- (void)viewDidLoad {
    [super viewDidLoad];
    _originalViewFrame = self.view.frame;
}

View Controllerをキーボード通知用のオブザーバとして追加する

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

オブザーバを削除

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

表示されたらキーボードで覆われた領域を保存し、表示されなくなったらCGRectZeroに設定します 

- (void)keyboardWasShown:(NSNotification *)notification{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    _keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height);
    [self moveTextFieldUP];

}
- (void) keyboardWillHide:(NSNotification *)notification{
    _keyBoardRect = CGRectZero;
    [self setDefaultFrame];
}

アクティブなテキストフィールドを保存する 

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    _activeTextField = textField;
//When keyboard is already present but the textfield is hidden. Case:When return key of  keyboard makes the next textfield as first responder
    if (!CGRectIsEmpty(_keyBoardRect)) { 
        [self moveTextFieldUP];
    }
    return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
}

今度はビューのフレームを変更する必要があります

- (void)moveTextFieldUP{
    CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.Origin.y, _activeTextField.frame.size.width, _activeTextField.frame.Origin.y+_activeTextField.frame.size.height);
    if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) {
        CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect);
        CGFloat newY = _originalViewFrame.Origin.y - intersectRect.size.height;
        CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height;
        CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING);
        [UIView animateWithDuration:0.3 animations:^{
            [self.view setFrame:newFrame];
        }];

        NSLog(@"Intersect");
    }
}
- (void)setDefaultFrame {
    [UIView animateWithDuration:0.3 animations:^{
        [self.view setFrame:_originalViewFrame];
    }];
}
2
PKN

ここにはたくさんの答えがありますが、これはうまくいき、他のものよりはるかに短いのです。

- (void)textFieldDidBeginEditing:(UITextField *)sender
{
    UIScrollView *scrollView = (UIScrollView *)self.view; // assuming this method is pasted into the UIScrollView's controller
    const double dontHardcodeTheKeyboardHeight = 162;
    double textY = [sender convertPoint:CGPointMake(0, 0) toView:scrollView].y;
    if (textY - scrollView.contentOffset.y + sender.frame.size.height > self.view.frame.size.height - dontHardcodeTheKeyboardHeight)
        [scrollView setContentOffset:CGPointMake(0.0, textY - 10) animated:YES];
}
2
Nestor

簡単かつ自動的に そのテキストフィールドがテーブルのセル内にある場合(table.scrollable = NOの場合でも)。

  • _ note _ that:テーブルの位置と大きさは妥当なものでなければなりません。例:
    • tableのy位置がビューの下から100の位置にある場合、300の高さのキーボードはテーブル全体と重なります。
    • テーブルの高さ= 10で、キーボードが表示されるために表示されるときにその中のテキストフィールドを100スクロールアップする必要がある場合、そのテキストフィールドはテーブルの範囲外になります。 
2
samthui7
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField {

  [self slideUp];
   return YES;
}

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

    [self slideDown];
   return YES;
}

#pragma mark - Slide Up and Down animation

- (void) slideUp {
    [UIView beginAnimations:nil context:nil];
    layoutView.frame = CGRectMake(0.0, -70.0, layoutView.frame.size.width, layoutView.frame.size.height);

    [UIView commitAnimations];
}


- (void) slideDown {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelay: 0.01]; 
    layoutView.frame = CGRectMake(0.0, 0.0, layoutView.frame.size.width, layoutView.frame.size.height);
    [UIView commitAnimations];
}

このスレッドには十分な答えがありますが、Appleがキーパッドの高さを考慮に入れるのと同じように、もっと単純でありながら一般化された方法をお勧めします。 Appleのアプローチ ここ にはいくつか問題がある。

これが私のアプローチです(Appleのやり方を少し修正しました) -

// Called when the UIKeyboardDidShowNotification is sent.
- (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.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}
2
Sam92

それは簡単です:-

TextFieldDidBeginEditingの場合: -

self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-150, self.view.frame.size.width, self.view.frame.size.height);

TextFieldShouldEndEditingでは、 -

self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+150, self.view.frame.size.width, self.view.frame.size.height);
1
dreamBegin

IQKeyboardManagerを使用して、キーボードが表示されるとUITextFieldとUITextViewは自動的にスクロールします。 Gitリンク: https://github.com/hackiftekhar/IQKeyboardManager

ポッド:ポッド 'IQKeyboardManager'#iOS8以降

ポッド 'IQKeyboardManager'、 '3.3.7'#iOS7

1

TextFieldsを使ったScrollviewのための簡単な解決法は以下の通りです、何の制約もアクティブなテキストフィールドなども必要ありません... 

 override func viewWillAppear(_ animated: Bool){
        super.viewWillAppear(animated)
        registerForKeyboardNotifications();


    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        deregisterFromKeyboardNotifications();
    }
    //MARK:- KEYBOARD DELEGATE METHODS
        func registerForKeyboardNotifications(){
            //Adding notifies on keyboard appearing
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func deregisterFromKeyboardNotifications(){
            //Removing notifies on keyboard appearing
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func keyboardWasShown(notification: NSNotification){

            var info = notification.userInfo!
            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = (keyboardSize?.height)!
            scrRegister.contentInset = contentInset


        }
        func keyboardWillBeHidden(notification: NSNotification)
        {
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = 0
            scrRegister.contentInset = contentInset

        }
1
Jaydeep Vyas

1つのビューを配置してからそのビューにテキストフィールドを配置し、キーボードが表示されたときにデリゲートによってイベントを検出します。そのビューのある位置も)、それからあなたのビューはその位置に上がるでしょう。ビューをアニメートするのと同じことです。

ありがとう

1
user1240409

Swift 3.0バージョン Applesのキーボード管理コードはこちら: FloatingTF 以下のコードで使用されているのは、iOSのマテリアルデザインベースのテキストフィールドです。

import UIKit
class SignupViewController: UIViewController, UITextFieldDelegate {

    //MARK: - IBOutlet:
@IBOutlet weak var emailTF: FloatingTF!
@IBOutlet weak var passwordTF: FloatingTF!
@IBOutlet weak var dobTF: FloatingTF!

@IBOutlet weak var scrollView: UIScrollView!

//MARK: - Variable:
var activeTextField: UITextField!

//MARK: - ViewController Lifecycle:
override func viewDidLoad() {
    super.viewDidLoad()        
    emailTF.delegate = self
    passwordTF.delegate = self
    dobTF.delegate = self 
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

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

   deRegisterKeyboardNotifications()
}

//MARK: - Keyboard notification observer Methods
fileprivate func registerKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func deRegisterKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {

    let info: NSDictionary = notification.userInfo! as NSDictionary
    let value: NSValue = info.value(forKey: UIKeyboardFrameBeginUserInfoKey) as! NSValue
    let keyboardSize: CGSize = value.cgRectValue.size
    let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0)
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.Origin
    if (!aRect.contains(activeTextFieldOrigin!)) {
        scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
    }    }

func keyboardWillHide(notification: NSNotification) {
    let contentInsets: UIEdgeInsets = .zero
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets
}

//MARK: - UITextField Delegate Methods
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if textField == emailTF {
        passwordTF.becomeFirstResponder()
    }
    else if textField == passwordTF {
        dobTF.becomeFirstResponder()
    }
    else {
        self.view.endEditing(true)
    }
    return true
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    activeTextField = textField
    scrollView.isScrollEnabled = true
}

func textFieldDidEndEditing(_ textField: UITextField) {
    activeTextField = nil
    scrollView.isScrollEnabled = false
}
}
1
abhi1992

これは私のために働いた:

func setupKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWasShown:"), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillBeHidden:"), name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height -= kbSize.height

    self.view.frame = rect
    UIView.commitAnimations()
}

func keyboardWillBeHidden(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height += kbSize.height
    self.view.frame = rect
    UIView.commitAnimations()
}
0
fede1608

テキストフィールドを画面の一番下に配置する必要がある場合、最も不思議な解決策は、ビューコントローラを次のように上書きすることです。

override var inputAccessoryView: UIView? {
    return <yourTextField>
}
0

Swift 4.1用のコードをユーザー入力できます

    let keyBoardSize = 80.0

    func keyboardWillShow() {

    if view.frame.Origin.y >= 0 {
    viewMovedUp = true
     }
     else if view.frame.Origin.y < 0 {
    viewMovedUp = false
   }
  }

func keyboardWillHide() {
 if view.frame.Origin.y >= 0 {
    viewMovedUp = true
 }
 else if view.frame.Origin.y < 0 {
    viewMovedUp = false
 }

}

func textFieldDidBeginEditing(_ textField: UITextField) {
   if sender.isEqual(mailTf) {
    //move the main view, so that the keyboard does not hide it.
    if view.frame.Origin.y >= 0 {
        viewMovedUp = true
    }
  }
}

func setViewMovedUp(_ movedUp: Bool) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
    // if you want to slide up the view
let rect: CGRect = view.frame
if movedUp {

    rect.Origin.y -= keyBoardSize
    rect.size.height += keyBoardSize
}
else {
    // revert back to the normal state.
    rect.Origin.y += keyBoardSize
    rect.size.height -= keyBoardSize
 }
 view.frame = rect
 UIView.commitAnimations()
}

func viewWillAppear(_ animated: Bool)  {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}

func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
0
Pankaj Jangid

(BOOL)textFieldShouldBeginEditing:(UITextField *)textField

if (textField.frame.Origin.y > self.view.frame.size.height - 216)
    {
        if (screenHeight>500)
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 100);
        else
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 216);
        CGPoint scrollPoint = CGPointMake(0.0,(textField.frame.Origin.y - (self.view.frame.size.height - 216 - textField.frame.size.height - 20)));
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
    [scrollView setScrollEnabled:YES];

keyBoardを辞任するときあなたは以下のコードを書く必要があります

scrollView.contentSize = CGSizeMake(0.0, 640);
CGPoint scrollPoint = CGPointMake(0.0,0.0);
[scrollView setContentOffset:scrollPoint animated:YES]; 
0
PVCS

Swift Developerの場合、Swift 3を使用して、レポがあります https://github.com/jamesrochabrun/KeyboardWillShow

import UIKit

class ViewController: UIViewController {

    //1 Create a view that will hold your TEXTFIELD
    let textField: UITextField = {
        let tf = UITextField()
        tf.translatesAutoresizingMaskIntoConstraints = false
        tf.layer.borderColor = UIColor.darkGray.cgColor
        tf.layer.borderWidth = 3.0
        return tf
    }()
    //2 global variable that will hold the bottom constraint on changes
    var textfieldBottomAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        //3 add the view to your controller
        view.addSubview(textField)
        textField.heightAnchor.constraint(equalToConstant: 80).isActive = true
        textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
        textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        textfieldBottomAnchor?.isActive = true

        setUpKeyBoardObservers()
    }
    //4 Use NSnotificationCenter to monitor the keyboard updates
    func setUpKeyBoardObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    //5 toggle the bottom layout global variable based on the keyboard's height
    func handleKeyboardWillShow(notification: NSNotification) {

        let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect
        if let keyboardFrame = keyboardFrame {
            textfieldBottomAnchor?.constant = -keyboardFrame.height
        }
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }

    func handleKeyboardWillHide(notification: NSNotification) {

        textfieldBottomAnchor?.constant = 0
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
    //6 remove the observers
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NotificationCenter.default.removeObserver(self)
    }
}
0
James Rochabrun

IOSでは、キーボードを上に動かしてアプリ内のテキストフィールドに戻すことは少し混乱し、同じ方法をいくつか実装する必要があります。テキストフィールドが存在するすべてのクラスで繰り返されます。

私はこのGithubコントロールを使用することを好みます。 

IQキーボード

その中で私たちは何もする必要はありません。 - ドロップコントロール をプロジェクトにドラッグ&ビルドするだけです。 - それはあなたのアプリのためにすべてをするでしょう。

ありがとう 

これは役に立つでしょう。

0
Esha

私が使い始めた解決策は@DK_であることがわかりました。ただし、scrollViewがビュー全体をカバーするという仮定があります。そうではありませんでした。キーボードがログイン画面の下のテキストフィールドを覆っている場合に備えて、私はscrollViewが欲しいだけでした。そのため、私のコンテンツビューは私のスクロールビューと同じサイズで、メインビューより小さかった。

それはまた私が最初にトラブルに遭遇した場所である風景を説明しませんでした。数日間それを試した後、これは私のkeyboardWasShown:メソッドです。

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    // A lot of the inspiration for this code came from http://stackoverflow.com/a/4837510/594602
    CGFloat height = 0;
    NSDictionary* info = [aNotification userInfo];

    CGRect kbFrameRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect kbBoundsRect = [self.view convertRect:kbFrameRect fromView:nil]; // Convert frame from window to view coordinates.

    CGRect scrollRect = scrollView.frame;
    CGRect intersect = CGRectIntersection(kbBoundsRect, scrollRect);

    if (!CGRectIsNull(intersect))
    {
        height = intersect.size.height;
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // Figure out what the view rectangle is for the scrollView
    CGPoint contentOffset = scrollView.contentOffset;
    CGRect visibleRect = CGRectOffset(scrollRect, contentOffset.x, contentOffset.y);    // I'm not 100% sure if this is needed/right. My scrollView was always at the top in testing.
    visibleRect.size.height -= height;
    CGRect activeRect = activeField.frame;

    if (!CGRectContainsRect(visibleRect, activeRect))
    {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

また、自動レイアウトを使用するのに苦労しました。レイアウトが正しく行われていないと、思ったようにスクロールしません。もっと楽になりました1つのことは、スクロールされることになっていたすべての項目を単一のビューに配置し、それをスクロールビューの唯一の項目として配置することでした。私はその単一のビューを「コンテンツビュー」と呼びました。

重要なのは、コンテンツビューの幅と高さが設定されていることです。これにより、スクロールビューは処理する必要があるコンテンツの量を正確に知ることができました。これは通常のレイアウトから少し後退したものです。通常、ビューはできるだけ多くのスペースを取ろうとしています。スクロールビューの内容を使用して、ビューをできるだけ閉じ込めるようにします。コンテンツビューでは、これをやめることができます。だから私は248の高さを私に与え、そして私の幅として320の標準スクリーン幅を使った。

最終的に私のために働いたレイアウトはこれらでした:

  • スーパービューにスクロールビュー:基本的に私は上、左、そして右に制約を与えました。
    • Horizontal Space - View - Scroll View(0)
    • Vertical Space - View - Scroll View(0)
    • Horizontal Space - Scroll View - View(0)
  • スクロールビューの高さ:スクロールビューを一定の高さに設定します。これが本当に必要であるかどうかはわかりませんが、スクロールビュー自体の範囲を超えてしまいました。
    • Height - (248) - Scroll View
  • コンテンツビューからスクロールビューへ:私は上下左右の四方に定数を与えました。
    • Vertical Space - View - Scroll View(0)
    • Vertical Space - Scroll View - View(0)
    • Horizontal Space - View - Scroll View(0)
    • Horizontal Space - Scroll View - View(0)
  • コンテンツビューの大きさ。
    • Height - (248) - View
    • Width - (320) - View
0
Erik Allen

あなたはこの単純なGitリポジトリを使うことができます: https://github.com/hackiftekhar/IQKeyboardManager

これは自動的にすべてのフィールドの移動を管理するライブラリです。

彼らのreadmeによると、統合はとても簡単です。

コードを入力する必要はありませんおよび追加の設定は不要です。 IQKeyboardManagerを使用するには、単にプロジェクトにソースファイルを追加する必要があります

ただし、これは非常に優れた制御方法ですが、スクロールビューを使用するView Controllerの場合のように、競合が発生することがあります。コンテンツサイズが変わることがあります。それでも、あなたはそれのために行くことができ、あなたの要求に従ってそれを試すことができます多分あなたは私が逃したことをすることができました。

0
Harminder Singh

ライブおよびロードされたiphoneのUICatalogViewの例を参照してください。

0
Ankit Sachan

テキストフィールドの変更や内容の編集中にデフォルトのメインビューにリセットすると問題が発生しました(たとえば、電話テキストフィールドと ' - '記号を追加し、ビューがテキストフィールドを覆って戻る)次のように、通知デリゲート関数内のフレームサイズや位置ではなく、レイアウトや変更の制約が一定です。

P.S私は単純にビューを上に移動するだけでscrollviewを使用していませんが、それは同様に動作するはずです

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    if !keyboardIsShown{
        self.infoViewTopConstraint.constant -= keyboardSize.height
        self.infoViewBottomConstraint.constant += keyboardSize.height
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
        keyboardIsShown = true
    }
}

func keyboardWillHide(notification: NSNotification) {
if keyboardIsShown {
    self.infoViewTopConstraint.constant += keyboardSize.height
    self.infoViewBottomConstraint.constant -= keyboardSize.height
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
    keyboardIsShown = false
}
0
Robert Juz

この質問にはすでにたくさんの答えがあります。ある人はスクロールビューを使うと言い、ある人は第3のライブラリを使うと言いました。

しかし、私にとっては、解決策は静的セルを含むUITableViewControllerであるべきです。

あなたはUIを複数の部分に分けてそれらを一つずつtableViewCellsに入れるでしょう、もうあなたはキーボードを心配する必要はなく、tableViewControllerはあなたのためにそれを自動的に管理します。 

パディング、マージン、セルの高さを計算するのは少し難しいかもしれませんが、あなたの数学が問題なければ、それは簡単です。

0
JIE WANG

私はSwiftと自動レイアウトを使います(しかし、前のSwiftの答えについてはコメントできません)。スクロールビューを使わずにこれを行う方法は次のとおりです。

私は自分のフォームをフィールド間に垂直方向の制約を付けてIBでレイアウトし、それらを分離します。一番上のフィールドからコンテナビューに垂直方向の拘束を追加し、それに対するアウトレットを作成します(以下のコードではtopSpaceForFormConstraint)。必要なのは、この制約を更新することだけです。これは、Niceソフトモーション用のアニメーションブロックで行います。高さのチェックはもちろんオプションです、この場合、私はちょうど最小の画面サイズのためにそれをする必要がありました。

これは通常のtextFieldDidBeginEditingまたはkeyboardWillShowメソッドのいずれかを使用して呼び出すことができます。 

func setFormHeight(top: CGFloat)
{
    let height = UIScreen.mainScreen().bounds.size.height

    // restore text input fields for iPhone 4/4s
    if (height < 568) {
        UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: {
            self.topSpaceForFormConstraint.constant = top
            self.view.layoutIfNeeded()
            }, completion: nil)
    }

}
0
Anthony Scott

この可能性はここでは見られなかったので、答えでメソッドを試したが、数時間後にiOS6/7のXCode 5に はるか より簡単な方法があることを発見したので追加します。 NSLayoutConstraintsを使用してください。

参照項目: 自動レイアウト制限 - キーボード

これが私のコードです:

.mファイル:

// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
    NSLog(@"keyboardWillBeShown:");
    [self.PhoneNumberLabelOutlet setHidden:TRUE];
    CGFloat heightOfLabel = self.PhoneNumberLabelOutlet.frame.size.height;
    for( NSLayoutConstraint* thisConstraint in self.topElementsVerticalDistanceFromTopLayoutConstraint ) {
        thisConstraint.constant -= heightOfLabel;
    }

    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGFloat oldConstant = [self.SignInYConstraint constant];
    self.SignInYConstraint.constant = oldConstant + kbSize.height;
    [self.view setNeedsUpdateConstraints];

    NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        [self.view layoutIfNeeded];
    }];

}

.hファイル:

#import <UIKit/UIKit.h>

@interface SignInViewController : UIViewController {

    UITextField* _activeField;
}




- (void)signInCallback:(NSObject*)object;


@property (weak, nonatomic) IBOutlet UILabel *PhoneNumberLabelOutlet;

@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *ActivityIndicatorOutlet;

@property (weak, nonatomic) IBOutlet UITextField *UserIDTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UITextField *PasswordTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UIButton *SignInButton;

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *SignInYConstraint;

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *topElementsVerticalDistanceFromTopLayoutConstraint;

@end
0
xaphod

Swift 5

viewDidLoadまたはviewDidAppear add addKeyboardObserversメソッドで。

fileprivate func addKeyboardObservers(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

fileprivate func removeKeyboardObservers(){
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}


@objc fileprivate func keyboardWillHide(_ notification: Notification){
    if (window == nil) {return}
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = .zero
}


@objc fileprivate func keyboardWillShow(_ notification: Notification){
    if (window == nil) {return}
    if UIApplication.shared.applicationState != .active { return }

    // keyboard height
    guard let height = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height else {return}
    // keyboard present animation duration
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = height
}

deinitでオブザーバーを削除するか、消えることを忘れないでください

    self.removeKeyboardObservers()

私は少し遅れています。あなたのviewControllerにscrollViewを追加する必要があります。 

2以下の方法で実施する必要があります。

TextFieldデリゲートメソッド。

    - (void)textFieldDidBeginEditing:(UIView *)textField {
    [self scrollViewForTextField:reEnterPINTextField];
}

そして、デリゲートメソッドで以下のメトンを呼び出します。

 - (void)scrollViewForTextField:(UIView *)textField {
    NSInteger keyboardHeight = KEYBOARD_HEIGHT;

    if ([textField UITextField.class]) {
        keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
    } 

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
    aRect.size.height -= keyboardHeight;
    CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
    CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);

    if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
        CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
        [contentSlidingView setContentOffset:scrollPoint animated:YES];
    }
}
0
Emre Gürses

私の5セントを追加してください:)

私はいつもinputTextFieldまたはscrollViewのためにtableViewを使うことを好みます。通知と組み合わせると、そのような動作を簡単に管理できます。 (TableViewで静的セルを使用する場合は、このような動作が自動的に管理されます。)

// MARK: - Notifications
fileprivate func registerNotificaitions() {
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

fileprivate func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self)
}

@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        view.layoutIfNeeded()
        UIView.animate(withDuration: 0.3, animations: {
            let heightInset = keyboardHeight - self.addDeviceButton.frame.height
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

@objc fileprivate func keyboardWillDisappear() {
    view.layoutIfNeeded()
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset = UIEdgeInsets.zero
        self.view.layoutIfNeeded()
    }, completion: nil)
}
0
gbk