1761

iOS SDK の場合:

キーボードを表示するUIViewwith UITextFields があります。次のことができるようにする必要があります。

  1. UIScrollViewキーボードが表示されたら、コンテンツのスクロールを許可して、他のテキスト フィールドを表示します。

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

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

UIViewaと a の両方が必要UIScrollViewですか? 一方が他方の内側に入りますか?

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

理想的には、可能な限り多くのコンポーネントの設定を Interface Builder で行います。必要な部分だけコードを書きたい。

注:私が使用しているUIView(または) は、通常どおり機能する必要があるタブバー ( ) によって表示されます。UIScrollViewUITabBar


キーボードが表示されたときのためだけにスクロールバーを追加しています。必要ではありませんが、ユーザーがスクロールしてテキストボックスを変更できるなど、より良いインターフェイスを提供するように感じます。

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
}

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

4

98 に答える 98

1063
  1. ScrollView今持っているコンテンツがiPhoneの画面に収まらない場合にのみ必要です。(キーボードが表示されたときに上にスクロールするScrollViewためだけにコンポーネントのスーパービューとしてを追加する場合は、必要ありません。)TextField

  2. がキーボードで覆われないようにする標準的な方法TextFieldは、キーボードが表示されているときは常にビューを上下に移動することです。

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

#define kOFFSET_FOR_KEYBOARD 80.0

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

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

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

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

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

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

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

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

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}
于 2009-07-14T18:03:55.057 に答える
448

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

UIScrollView適切にスクロールしない 場合に考慮すべき点がいくつかあります。

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

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

3) 問題は次のとおりです。これを最初に実装したときCGRect、編集したテキスト フィールドを取得してUIScrollView'sscrollRecToVisible メソッドを呼び出す必要があると考えました。メソッドの呼び出しでUITextFieldDelegateメソッドを実装しました。これは実際には、スクロールが所定の位置にスナップするという奇妙な副作用で機能しました。長い間、それが何であるかを理解できませんでした。次に、Delegate メソッドをコメントアウトすると、すべて機能します!!(???)。結局のところ、現在編集されているものを暗黙的に表示可能なウィンドウに暗黙的に表示すると思います。メソッドの実装とその後の への呼び出しは冗長であり、奇妙な副作用の原因でした。textFieldDidBeginEditingscrollRecToVisibleUITextFieldtextFieldDidBeginEditingUIScrollViewUITextFieldUITextFieldDelegatescrollRecToVisible

したがって、キーボードが表示されたときにUITextField適切にスクロールする手順は次のとおりです。UIScrollView

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

- (void)viewDidLoad 
{
    [super viewDidLoad];

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

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

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


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

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

    keyboardIsShown = NO;
}

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

    NSDictionary* userInfo = [n userInfo];

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

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

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. でキーボード通知に登録します。viewDidLoad
  2. でキーボード通知の登録を解除します。viewDidUnload
  3. が設定されていて、 atcontentSizeよりも大きいことを確認してくださいUIScrollViewviewDidLoad
  4. UIScrollViewキーボードが存在する場合は縮小します
  5. UIScrollViewキーボードがなくなったら元に戻します。
  6. UITextFieldivar を使用して、キーボードがすでに存在している場合でもタブが押されるたびにキーボード通知が送信されるため、キーボードが既に画面に表示されているかどうかを検出して、既に縮小されているときに縮小しないようにします。UIScrollView

注意すべきことの 1 つはUIKeyboardWillShowNotification、キーボードが既に画面上にある場合でも、別の をタップしたときに が起動することですUITextFieldUIScrollViewキーボードが既に画面に表示されているときにサイズを変更しないように、ivar を使用してこれを処理しました。UIScrollViewキーボードが既に存在する場合に、うっかりサイズを変更すると悲惨なことになります!

このコードがあなたの頭痛の種から解放されることを願っています。

于 2010-04-24T08:31:04.407 に答える
274

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)
于 2011-01-29T14:56:02.380 に答える
249

次のように関数textFieldDidBeginEdittingを呼び出します。textFieldDidEndEditing[self animateTextField:textField up:YES]

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

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

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

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

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

このコードがお役に立てば幸いです。

スイフト5

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.animate(withDuration: movementDuration, delay: 0, options: [.beginFromCurrentState], animations: {
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
    }, completion: nil)
}

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

func textFieldDidEndEditing(_ textField: UITextField) {
    animateTextField(textField: textField, up:false)
}
于 2011-08-02T06:48:20.497 に答える
135

TextFieldsを使用するだけです:

1a) 使用Interface Builder: すべての TextField を選択 => 編集 => 埋め込み => ScrollView

1b) scrollView と呼ばれる UIScrollView に TextFields を手動で埋め込む

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];
}
于 2012-12-01T14:53:19.257 に答える
119

Universal Solutionの場合、 IQKeyboardManagerを実装するための私のアプローチは次のとおりです。

ここに画像の説明を入力

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

Step2:-見つかった場合UIKeyboardWillShowNotificationUITextFieldTextDidBeginEditingNotificationまたはUITextViewTextDidBeginEditingNotification通知があった場合、階層topMostViewControllerからインスタンスを取得しようとします。UIWindow.rootViewController適切に露出させるには、UITextFieldのフレームを調整する必要があります。UITextViewtopMostViewController.view

Step3:-最初に応答した/topMostViewController.viewに関しての予想移動距離を計算しました。UITextFieldUITextView

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

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

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

Step7:-topMostViewController.view.frame乱れた距離に合わせて下に戻しました。

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

コード行なしでIQKeyboardManagerが行うのはこれだけです!! 関連するソース ファイルをプロジェクトにドラッグ アンド ドロップするだけです。IQKeyboardManagerは、 Device OrientationAutomatic UIToolbar ManagementKeybkeyboardDistanceFromTextFieldなど、想像以上に多くの機能もサポートしています。

于 2013-07-17T18:18:21.147 に答える
102

キーボードの邪魔にならないように、その中のすべてのテキストフィールドを移動することを処理する、ユニバーサル、ドロップインUIScrollViewUITableViewさらにはサブクラスをまとめました。UICollectionView

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

UITableView基本的に、ベースのインターフェース、または手動で配置されたビューで構成されるインターフェースのいずれかのセットアップで動作するはずです。

Here' tis:テキストフィールドをキーボードの邪魔にならないように移動するためのソリューション

于 2011-04-12T11:33:16.373 に答える
93

Swiftプログラマーの場合:

これらをView Controllerクラスに入れ、View Controllerに実装しUITextFieldDelegate、textFieldのデリゲートをに設定するだけですself

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

Swift 4、4.2、5 の場合: 変更

self.view.frame = CGRectOffset(self.view.frame, 0,  movement)

self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)

この実装に関する最後の注意: キーボードが表示されている間に別のビュー コントローラーをスタックにプッシュすると、ビューが中央のフレームに戻されるというエラーが発生しますが、キーボード オフセットはリセットされません。たとえば、キーボードが nameField の最初のレスポンダーですが、ヘルプ ビュー コントローラーをスタックにプッシュするボタンを押します。オフセット エラーを修正するには、ビュー コントローラを終了する前に nameField.resignFirstResponder() を呼び出して、textFieldDidEndEditing デリゲート メソッドも呼び出されるようにします。これは viewWillDisappear メソッドで行います。

于 2015-04-30T11:21:08.927 に答える
66

すでに多くの答えがありますが、それでも上記の解決策のどれも、「完璧な」バグや下位互換性があり、ちらつきのないアニメーションに必要なすべての凝ったポジショニングのものを持っていませんでした。(フレーム/境界と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];
}
于 2013-03-01T19:41:24.457 に答える
63

Shiun 氏は次のように述べています。iOS >= 3.2 で UITextField を表示するには、明示的な scrollRectToVisible を追加する必要がありました。

于 2010-11-06T05:25:02.537 に答える
48

UITextField考慮すべきことの 1 つは、aを単独で使用するかどうかです。UITextFields実際に .NET以外で使用する、適切に設計された iPhone アプリに出会ったことがありませんUITableViewCells

余分な作業が必要になりますが、すべてのデータ入力ビューとテーブル ビューを実装することをお勧めします。に a を追加UITextViewしますUITableViewCells

于 2009-07-20T08:18:51.973 に答える
47

このドキュメントでは、この問題の解決策について詳しく説明します。「キーボードの下にあるコンテンツの移動」の下のソース コードを見てください。それはかなり簡単です。

編集:例にわずかな不具合があることに気付きました。UIKeyboardWillHideNotificationの代わりにfor を聞きたいと思うでしょうUIKeyboardDidHideNotification。そうしないと、キーボードを閉じるアニメーションの間、キーボードの後ろのスクロール ビューが切り取られます。

于 2010-10-28T12:37:34.870 に答える
32

見つかった最も簡単な解決策

- (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];
}
于 2014-10-25T11:10:22.527 に答える
31

多くの 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 on 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 on 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];
}
于 2010-02-11T11:18:14.190 に答える
30

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

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

else
{
    // revert back to the normal state.
    rect.origin.y += kOFFSET_FOR_KEYBOARD;
    rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
于 2010-02-05T18:27:10.670 に答える
23

元の表示状態に戻すには、次を追加します。

-(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];
    }
}
于 2010-02-10T16:30:02.817 に答える
22

ビューを上に移動することが正しいアプローチであるかどうかはわかりません。UIScrollViewのサイズを変更して、別の方法でそれを行いました。ちょっとした記事で詳しく説明しました。

于 2010-01-10T14:38:59.273 に答える
18

@ user271753

ビューを元に戻すには、次を追加します。

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
   [textField resignFirstResponder];
   [self setViewMovedUp:NO];
   return YES;
}
于 2010-10-29T08:32:57.813 に答える
16

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

このサブクラスを使用するには、カスタム ビュー コントローラーをGMKeyboardVCのサブクラスにし、この機能を継承します (実装する場合は、スーパーを呼び出す必要があることを確認してくださいviewWillAppear) viewWillDisappear。クラスはgithubにあります。

于 2011-09-10T14:43:45.457 に答える
14

スイフト 4

UITextField上下またはUIViewで簡単に移動できUIKeyBoardますAnimation ここに画像の説明を入力

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
    }

}
于 2018-01-26T10:48:34.010 に答える
12

これは、特定のレイアウトに対して私が思いついたハックソリューションです。このソリューションは、セクションをスクロールして表示するという点で 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 用であり、内部レイアウト エンジンを学習する日数はありませんでした。

于 2010-03-28T21:24:26.990 に答える
12

docsによると、iOS 3.0 以降、UITableViewControllerテキスト フィールドのインライン編集があると、クラスはテーブル ビューのサイズと位置を自動的に変更します。一部の人が示しているように、テキスト フィールドを a 内に配置するだけでは不十分だと思いUITableViewCellます。

ドキュメントから:

テーブル ビュー コントローラーは、テーブル ビューの行のインライン編集をサポートします。たとえば、編集モードで行にテキスト フィールドが埋め込まれている場合、表示されている仮想キーボードの上で編集中の行をスクロールします。

于 2012-10-04T02:44:03.970 に答える
11

ここで、キーパッドを処理する最も簡単なソリューションを見つけました。

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

ステップ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];
}

参照:まあ、この美しいコードスニップ、クリーンなソリューションを共有してくれたこの男に感謝してください。

これが誰かの役に立つことを願っています。

于 2015-08-19T17:45:32.640 に答える
10

このテーマに関する初心者向けの優れたチュートリアルを探していて、ここで最高のチュートリアルを見つけました。

MIScrollView.hチュートリアルの下部にある例では、必ず次の場所にスペースを入れてください。

@property (nonatomic, retain) id backgroundTapDelegate;

ご覧のとおり。

于 2012-01-01T19:23:15.350 に答える
10

1行も書く必要のないこのサードパーティを使用してください

https://github.com/hackiftekhar/IQKeyboardManager

プロジェクトをダウンロードし、プロジェクトにドラッグ アンド ドロップIQKeyboardManagerします。問題が見つかった場合は、READMEドキュメントをお読みください。

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

于 2015-10-12T09:43:07.817 に答える
8

これは、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
    }

}
于 2014-12-17T10:22:20.083 に答える
8

:この回答は、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 で設定することに注意してください。これは、なんらかの理由で UIKeyboardWillShowNotification の後に textViewDidBeginEditing が呼び出されるためです。

-(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;
}
于 2014-07-02T20:06:33.993 に答える
7

スウィフト 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)

            })
        }
    }
于 2016-02-16T08:58:08.287 に答える
7

これを試して:

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:self.m_Sp_Contact])
    {
        [self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES];          
    }
}
于 2012-07-20T07:34:10.063 に答える
7

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

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、幅、高さの値を追加できます。

于 2012-01-11T10:47:00.880 に答える
6

これは、キーボードを処理するための無料のライブラリです。Keyboard-Handling-in-iPhone-Applications。コードを1行だけ書く必要があります。

[AutoScroller addAutoScrollTo:scrollView];

これは、フォームでキーボードを処理するのに最適です

于 2012-12-17T07:33:42.237 に答える
6

これをポッドファイルに追加するだけです->pod 'IQKeyboardManager'

以上で、すべてのキーボード、スクロールビュー、およびすべてを処理できます。

何もコーディングする必要はありません。より良い解決策が見つかりませんでした!

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

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

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

于 2017-03-06T08:28:23.040 に答える
6

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プロトコルは、ビュー全体をそれぞれ上下にアニメーション化する 2 つのメソッドに準拠するすべての UIViewController を提供します。

に準拠している場合、にKeyboardCapable準拠してKeyboardAnimatableいるすべての UIViewControllerKeyboardCapableも に準拠していKeyboardAnimatableます。カッコいい。

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

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関数でそれらを実行する必要があります。それはあなた次第です。

于 2016-03-17T12:20:16.610 に答える
5

はるかに洗練された解決策は、サブクラスを使用して(UIViewこれは常に適切であるとは限りませんが)、親のフレーム変更時にすべてのサブビューを再計算することです(そして賢明です:新しいフレームサイズが変更された場合にのみ再計算します。オーバーライドするときと呼び出す前CGRectEqualToRectに、新しいフレームを比較します)。これに対する唯一の落とし穴は、使用する予定のキーボードイベントをおそらくリッスンする必要があるということです(または、便利なカプセル化のために、それ自体でそれを行うことができます)。しかし、とだけ。これは、見た目がスムーズになるようにするためです(CGからの呼び出しを待つと、途切れ途切れになります)。setFrame[super setFrame:frame_]UIViewControllerUIViewUIKeyboardWillShowNotificationUIKeyboardWillHideNotification

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

素朴な実装はオーバーライドするdrawRect:(しない)ことであり、より良い実装は単に使用することですlayoutSubviews(そして、またはで、または、showまたはhideのいずれかで呼び出されるSINGLEメソッドでUIViewController[view]を呼び出すことができます)。setNeedsLayout

このソリューションは、キーボードオフセットのハードコーディング(分割されていない場合などに変更されます)を回避し、ビューが他の多くのビューのサブビューであり、適切に応答する可能性があることも意味します。

他に解決策がない場合を除いて、そのようなものをハードコーディングしないでください。frameOSは、適切に処理を行った場合に、(新しいサイズに基づいて)インテリジェントに再描画するだけで十分な情報を提供します。これははるかにクリーンであり、あなたが物事を行うべき方法です。(ただし、さらに良いアプローチがあるかもしれません。)

乾杯。

于 2012-01-30T17:07:13.970 に答える
5

autolayout を使用した私のバージョンは次のとおりです。

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

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

2) 次の制約を設定します。

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

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

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

  • V は S と同じ幅

  • スーパービューへの最新のボトム 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、それは動作します!

于 2014-10-09T16:00:39.820 に答える
5

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

-(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); 
}
于 2016-03-30T07:54:45.410 に答える
4

テキストフィールドデリゲートメソッドを使用して行うこともできます。以下のコードを確認してください。スクロールビューにテキストフィールドを配置すると、機能します。

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

注:ビューに応じて、cPoint.y-100の値を変更する必要があります。

于 2012-12-03T17:35:26.643 に答える
4

これは、デバイスに依存しないオフセット計算です。キーボードとテキストフィールドの間のオーバーラップの高さを取得します:

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 はオフセットです。

于 2016-03-22T10:23:13.660 に答える
3

UIViewController を拡張するシンプルなソリューション

https://github.com/damienromito/VisibleFormViewController

ここに画像の説明を入力

于 2015-01-22T18:21:34.080 に答える
3

私は最近、メッセージング アプリで作業しているときに、同様のシナリオに陥っていることに気付きました。キーボードの上部に貼り付けて、必要なことのほとんどを自動的に実行するカスタム UIView を作成しました

MessageComposerView


(ソース: thegameengine.org )

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

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

UIScrollView のサイズを変更/再構成するには、次のオプションのデリゲート メソッドを使用する必要があります。

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

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

于 2013-11-15T23:22:11.723 に答える
3

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

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];
       }
 }
于 2013-04-02T06:47:31.070 に答える
3

スクロールビューをビューに設定する

  - (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];
    }
于 2016-09-07T05:41:38.880 に答える
3

すべてを 1 つのクラスにまとめます。ビューコントローラーがロードされたら、次のコード行を呼び出すだけです。

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

サンプル プロジェクトのリンクは次のとおりです:
https://github.com/caohuuloc/KeyboardInsetScrollView

于 2015-05-06T07:33:16.623 に答える
3

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

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];
    }];
}
于 2015-02-26T14:34:15.487 に答える
2

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

- (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];
}
于 2016-03-18T04:37:39.763 に答える
2

これは完璧に機能します.スクロールビューは、テキストフィールドの位置によって自動的に調整されます.気分が良くなると確信しています.

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];
}
于 2016-02-24T10:46:24.810 に答える
2

シンプルなソリューションと最新のアニメーション 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);
        }];

    }
}
于 2015-07-22T20:07:08.743 に答える
2

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

}
于 2016-02-26T15:08:26.717 に答える
2

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

これにより、テキスト フィールドが自動的に上に移動します。

于 2016-10-27T06:01:41.503 に答える
2

ここにはたくさんの答えがありますが、これは機能し、ほとんどのものよりもはるかに短いです:

- (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];
}
于 2012-10-12T23:47:19.180 に答える
2

このコードは、キーボードの高さとテキスト フィールドの深さに基づいて、どれだけ上に移動する必要があるかを計算します。デリゲートを追加し、ヘッダーに 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;
于 2016-07-08T09:23:44.210 に答える
2

このスレッドには十分な回答がありますが、アップルがキーパッドの高さを考慮に入れるのと同じように、キーボードの上にカスタムツールバーを使用しているときに非常に役立つ、はるかに単純で一般化された方法を提案したいと思います。ただし、ここでのアップルのアプローチにはほとんど問題がありません。

ここに私のアプローチがあります(わずかに変更されたリンゴの方法)-

// 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;
}
于 2016-04-23T18:33:29.037 に答える
1

それは簡単です:-

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);
于 2016-10-11T10:08:33.010 に答える
1

次の手順に従ってください。役立つ場合があります。1つのビューを配置し、そのビューにテキストフィールドを配置し、キーボードが表示されたときにデリゲートによってイベントを検出し、その時点でビューをすぐにアニメーション化します(そのビューにも位置を割り当てることができます)。その後、ビューが上に移動しますビューを下にアニメーション化するために同じことを行います。

ありがとう

于 2012-07-25T08:59:13.870 に答える
0

テキストフィールドを変更したり、そのコンテンツを編集したりしているときにデフォルトのメインビューにリセットする際に問題がありました (たとえば、電話のテキストフィールドに「-」記号を追加すると、ビューがテキストフィールドをカバーして戻ってきます) 自動レイアウトを使用し、制約定数を変更することで、これを最終的に克服しました次のように、フレーム サイズや通知デリゲート関数の位置ではありません。

PS私は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
}
于 2016-11-02T15:47:46.920 に答える
0

ここではこの可能性が見られなかったので、回答のメソッドを試したので追加しますが、数時間後に 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
于 2014-01-17T11:33:28.483 に答える
0

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

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()
}
于 2015-04-06T18:54:39.010 に答える
0

We can user given code for 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)
}
于 2018-05-24T13:29:04.337 に答える
0

私の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)
}
于 2018-09-12T08:16:01.843 に答える
0

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

キーボードを辞任するときは、次のコードを記述する必要があります

scrollView.contentSize = CGSizeMake(0.0, 640);
CGPoint scrollPoint = CGPointMake(0.0,0.0);
[scrollView setContentOffset:scrollPoint animated:YES]; 
于 2014-03-01T10:24:46.013 に答える
-2

それでも問題が解決しない場合は、私の投稿を読んでください

私は今日解決策を思いつきました。この問題に関する多数の投稿と「チュートリアル」を読みましたが、いずれの場合も機能しません(ほとんどは相互のコピーアンドペーストです)。Apple が公式に提案した「解決策」でさえ機能せず、さらに、ランドスケープ モードではまったく機能しません。このような一般的な基本的な問題を解決する手段を開発者に与えなかったことは、Apple にとって恥ずべきことです。非常に専門的ではありません。このような驚くべきフレームワーク (Cocoa) と、そのような厄介な過小評価の問題。

さて、私の解決策: UIScrollView をルートビューにしてから、すべてをそこに入れます。次に、この KeyboardAwareController クラスからビュー コントローラーをサブクラス化します (scrollView および keyboardPadding メソッドを再定義することをお勧めします)。

// // KeyboardAwareController.h // ソシオパシー // // 13.01.14 に管理者によって作成されました。// Copyright (c) 2014 kuchumovn. 全著作権所有。///

#import <UIKit/UIKit.h>

@interface KeyboardAwareController : UIViewController <UITextFieldDelegate>

@end

// // KeyboardAwareController.m // ソシオパシー // // 13.01.14 に管理者によって作成されました。// Copyright (c) 2014 kuchumovn. 全著作権所有。///

#import "KeyboardAwareController.h"

@interface KeyboardAwareController ()

@end

@implementation KeyboardAwareController
{
    CGPoint scrollPositionBeforeKeyboardAdjustments;

    __weak UIScrollView* scrollView;

    UITextField* activeField;
}

- (id) initWithCoder: (NSCoder*) decoder
{
    if (self = [super initWithCoder:decoder])
    {
        scrollPositionBeforeKeyboardAdjustments = CGPointZero;
    }
    return self;
}

- (void) viewDidLoad
{
    [super viewDidLoad];
}

- (UIScrollView*) scrollView
{
    return (UIScrollView*) self.view;
}

- (CGFloat) keyboardPadding
{
    return 5;
}

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

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

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

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

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

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

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

    [self registerForKeyboardNotifications];
}

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

    [super viewWillDisappear:animated];
}

- (void) keyboardWillShow: (NSNotification*) notification
{
    //NSLog(@"keyboardWillShow");

    // force the animation from keyboardWillBeHidden: to end
    scrollView.contentOffset = scrollPositionBeforeKeyboardAdjustments;

    scrollPositionBeforeKeyboardAdjustments = CGPointZero;
}

// warning: i have no idea why this thing works and what does every line of this code mean
// (but it works and there is no other solution on the internets whatsoever)
// P.S. Shame on Apple for missing such a basic functionality from SDK (and many other basic features we have to hack and mess around with for days and nights)

- (void) keyboardDidShow: (NSNotification*) notification
{
    //NSLog(@"keyboardDidShow");

    UIWindow* window = [[[UIApplication sharedApplication] windows]objectAtIndex:0];
    UIView* mainSubviewOfWindow = window.rootViewController.view;

    CGRect keyboardFrameIncorrect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect keyboardFrame = [mainSubviewOfWindow convertRect:keyboardFrameIncorrect fromView:window];
    CGSize keyboardSize = keyboardFrame.size;

    CGRect visibleFrame = CGRectMake(0, 0, 0, 0);
    visibleFrame.origin = self.scrollView.contentOffset;
    visibleFrame.size = self.scrollView.bounds.size;

    CGFloat paddedKeyboardHeight = keyboardSize.height + self.keyboardPadding;

    //NSLog(@"visibleFrame %@", NSStringFromCGRect(visibleFrame));

    visibleFrame.size.height -= paddedKeyboardHeight;

    //NSLog(@"visibleFrame after keyboard height %@", NSStringFromCGRect(visibleFrame));

    if (CGRectContainsPoint(visibleFrame, activeField.frame.origin))
        return;

    scrollPositionBeforeKeyboardAdjustments = scrollView.contentOffset;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, activeField.frame.origin.y - visibleFrame.size.height + activeField.frame.size.height, 0);

    contentInsets = UIEdgeInsetsMake(0.0, 0.0, paddedKeyboardHeight, 0);

    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;

    CGSize scrollContentSize = self.scrollView.bounds.size;
    scrollContentSize.height += paddedKeyboardHeight;
    self.scrollView.contentSize = scrollContentSize;

    //NSLog(@"scrollView %@", NSStringFromCGRect(scrollView.frame));
    //NSLog(@"activeField %@", NSStringFromCGRect(activeField.frame));

    //[scrollView scrollRectToVisible:activeField.frame animated:YES];

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

    //NSLog(@"scrollPoint %@", NSStringFromCGPoint(scrollPoint));

    [self.scrollView setContentOffset:scrollPoint animated:YES];
}

- (void) keyboardWillBeHidden: (NSNotification*) notification
{
    //NSLog(@"keyboardWillBeHidden");

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    // this doesn't work when changing orientation while the keyboard is visible
    // because when keyboardDidShow: will be called right after this method the contentOffset will still be equal to the old value
    //[scrollView setContentOffset:scrollPositionBeforeKeyboardAdjustments animated:YES];

    [UIView animateWithDuration:.25 animations:^
    {
        self.scrollView.contentInset = contentInsets;
        self.scrollView.scrollIndicatorInsets = contentInsets;

        // replacement for setContentOffset:animated:
        self.scrollView.contentOffset = scrollPositionBeforeKeyboardAdjustments;
    }];
}

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

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

ご不明な点がございましたら、私のプロジェクトが github でホストされています: https://github.com/kuchumovn/sociopathy.ios

より良い説明のためにスクリーンショットも撮りました: ストーリーボード レイアウトのスクリーンショットを参照してください

于 2014-01-13T16:41:40.567 に答える
-9

まず第一に、ビューをスクロールする必要がないように、ページのデザインを改善することをお勧めします。多くのテキスト フィールドがある場合でも、ScrollView を使用する必要はありません。複雑になるだけです。コントローラーの元のビューの上部にコンテナー UIView を追加し、それらのテキスト フィールドをそのビューに配置するだけです。キーボードが表示または非表示になったら、アニメーションを使用してこのコンテナー ビューを移動します。

于 2015-01-22T07:56:29.377 に答える