74

UIViewがありますが、UIScrollView内にありません。キーボードが表示されたら、ビューを上に移動したいと思います。このソリューションを使用する前に:キーボードが存在するときにUITextFieldを上に移動するにはどうすればよいですか?

正常に動作していました。しかし、テキストフィールドにデータを挿入した後、別のビューに移動します。このページに戻ると、ジャンプするだけで、テキストフィールドが表示されませんでした。この問題に対するより良い解決策はありますか?

4

18 に答える 18

80

キーボードを表示および非表示にするには、次のコードを使用します

//Declare a delegate, assign your textField to the delegate and then include these methods

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    return YES;
}


- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];

    [self.view endEditing:YES];
    return YES;
}


- (void)keyboardDidShow:(NSNotification *)notification
{
    // Assign new frame to your view 
    [self.view setFrame:CGRectMake(0,-110,320,460)]; //here taken -110 for example i.e. your view will be scrolled to -110. change its value according to your requirement.

}

-(void)keyboardDidHide:(NSNotification *)notification
{
    [self.view setFrame:CGRectMake(0,0,320,460)];
}
于 2012-07-01T13:53:56.710 に答える
37

UIView全体をにラップする必要なしに一時的に物事をスクロールすることを管理する小さなカテゴリを書きましたUIScrollView。ここでの動詞「scroll」の使用は、おそらく理想的ではありません。スクロールビューが含まれていると思われるかもしれませんが、含まれていません。 UIView(またはUIViewサブクラス)の位置をアニメーション化しているだけです。

これには、私のフォームやレイアウトに適したマジックナンバーがたくさん埋め込まれていますが、あなたには適さない可能性があるため、特定のニーズに合わせてこれを調整することをお勧めします。

UIView + FormScroll.h:

#import <Foundation/Foundation.h>

@interface UIView (FormScroll) 

-(void)scrollToY:(float)y;
-(void)scrollToView:(UIView *)view;
-(void)scrollElement:(UIView *)view toPoint:(float)y;

@end

UIView + FormScroll.m:

#import "UIView+FormScroll.h"


@implementation UIView (FormScroll)


-(void)scrollToY:(float)y
{

    [UIView beginAnimations:@"registerScroll" context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.4];
    self.transform = CGAffineTransformMakeTranslation(0, y);
    [UIView commitAnimations];

}

-(void)scrollToView:(UIView *)view
{
    CGRect theFrame = view.frame;
    float y = theFrame.origin.y - 15;
    y -= (y/1.7);
    [self scrollToY:-y];
}


-(void)scrollElement:(UIView *)view toPoint:(float)y
{
    CGRect theFrame = view.frame;
    float orig_y = theFrame.origin.y;
    float diff = y - orig_y;
    if (diff < 0) {
        [self scrollToY:diff];
    }
    else {
        [self scrollToY:0];
    }

}

@end

それをUIViewControllerにインポートすると、次のことができます。

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self.view scrollToView:textField];
}

-(void) textFieldDidEndEditing:(UITextField *)textField
{
    [self.view scrollToY:0];
    [textField resignFirstResponder];
}

...または何でも。このカテゴリは、ビューの位置を調整するための3つの非常に優れた方法を提供します。

于 2012-07-01T13:53:33.273 に答える
32

ビューをキーボードにバインドすることもオプションです(回答の下部にあるGIFを参照)

スイフト4

拡張機能を使用する: (完全にはテストされていません)

extension UIView{
    func bindToKeyboard(){
        NotificationCenter.default.addObserver(self, selector: #selector(UIView.keyboardWillChange(notification:)), name: Notification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    func unbindToKeyboard(){
        NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillChangeFrame, object: nil)
    }
    @objc
    func keyboardWillChange(notification: Notification) {
        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

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y+=deltaY

        },completion: nil)

    }
}

スイフト 2 + 3

拡張機能を使用:

extension UIView{
    func bindToKeyboard(){
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UIView.keyboardWillChange(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil)
    }


    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


        UIView.animateKeyframesWithDuration(duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
                self.frame.origin.y+=deltaY

        },completion: nil)

    }  
}

使用法:

// view did load...
textField.bindToKeyboard()

...

// view unload
textField.unbindToKeyboard()

結果:
ここに画像の説明を入力

重要
ビューのアンロード時にオブザーバーを削除することを忘れないでください

于 2016-05-03T11:57:25.523 に答える
14

私はtheDuncs の回答が非常に役立つことを発見しました。以下に、私自身の (リファクタリングされた) バージョンを見つけることができます。


主な変更点

  1. 値をハードコーディングするのではなく、キーボードのサイズを動的に取得するようになりました
  2. コードの重複を防ぐために、UIView アニメーションを独自のメソッドに抽出しました。
  3. ハードコーディングするのではなく、メソッドに期間を渡すことができるようになりました

- (void)viewWillAppear:(BOOL)animated {
    [[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 {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    float newVerticalPosition = -keyboardSize.height;

    [self moveFrameToVerticalPosition:newVerticalPosition forDuration:0.3f];
}


- (void)keyboardWillHide:(NSNotification *)notification {
    [self moveFrameToVerticalPosition:0.0f forDuration:0.3f];
}


- (void)moveFrameToVerticalPosition:(float)position forDuration:(float)duration {
    CGRect frame = self.view.frame;
    frame.origin.y = position;

    [UIView animateWithDuration:duration animations:^{
        self.view.frame = frame;
    }];
}
于 2015-02-26T21:19:03.960 に答える
5

これを試してください:-

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


[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector (keyboardDidHide:)
                                                 name: UIKeyboardDidHideNotification object:nil];

-(void) keyboardDidShow: (NSNotification *)notif
    {
        CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height+[self getTableView].tableFooterView.frame.size.height, 0.0);

        [self getTableView].contentInset = contentInsets;
        [self getTableView].scrollIndicatorInsets = contentInsets;

        CGRect rect = self.frame; rect.size.height -= keyboardSize.height;
        if (!CGRectContainsPoint(rect, self.frame.origin))
        {
            CGPoint scrollPoint = CGPointMake(0.0, self.frame.origin.y - (keyboardSize.height - self.frame.size.height));
            [[self getTableView] setContentOffset:scrollPoint animated:YES];
        }
    }

-(void) keyboardDidHide: (NSNotification *)notif
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    [self getTableView].contentInset = contentInsets;
    [self getTableView].scrollIndicatorInsets = contentInsets;
}
于 2015-04-16T09:07:22.460 に答える
5

KeyBoard に関連するすべての問題については、IQKeyBoardManager を使用するだけで役に立ちます。 https://github.com/hackiftekhar/IQKeyboardManager .

于 2015-04-07T13:15:28.317 に答える
2

オブザーバー通知を追加しないシンプルなソリューション

-(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)textFieldDidEndEditing:(UITextField *)sender
{
     if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:NO];
        }
}

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

どこ

#define kOFFSET_FOR_KEYBOARD 80.0
于 2014-10-25T10:53:35.943 に答える
0

デリゲートを宣言し、テキスト フィールドをデリゲートに割り当ててから、これらのメソッドを含めます。

電子メールとパスワードのテキスト フィールドを含むログイン フォームがあると仮定すると、このコードは完全に適合します。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [self.emailTextField resignFirstResponder];
    [self.passwordTextField resignFirstResponder];

}

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

    if (self.emailTextField == textField) {
        [self.passwordTextField becomeFirstResponder];
    } else {
        [self.emailTextField resignFirstResponder];
        [self.passwordTextField resignFirstResponder];
    }
    return NO;
}
- (void)viewWillAppear:(BOOL)animated {
    [[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 {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

#pragma mark - keyboard movements
- (void)keyboardWillShow:(NSNotification *)notification
{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    [UIView animateWithDuration:0.3 animations:^{
        CGRect f = self.view.frame;
        f.origin.y = -0.5f * keyboardSize.height;
        self.view.frame = f;
    }];
}

-(void)keyboardWillHide:(NSNotification *)notification
{
    [UIView animateWithDuration:0.3 animations:^{
        CGRect f = self.view.frame;
        f.origin.y = 0.0f;
        self.view.frame = f;
    }];
}
于 2016-04-20T16:23:06.987 に答える
0

それがテーブルのセルにある場合は、簡単かつ自動的に実行できます( .textfieldtable.scrollable = NO

注意: テーブルの位置とサイズは適切でなければなりません。例えば:

  • テーブルの y 位置がビューの下部から数えて 100 の場合、高さ 300 のキーボードがテーブル全体に重なります。
  • テーブルの場合height = 10textfieldキーボードを表示するために 100 スクロールアップする必要がある場合、そのテキストフィールドはテーブルの範囲外になります。
于 2016-01-08T06:56:43.863 に答える