iOS點選輸入框時自動移動到鍵盤之上

weixin_33895657發表於2015-10-12

1. 概述

本文要實現的是在iOS上點選輸入框後,如果輸入框在鍵盤之下,那麼將自動移動介面使得輸入框在鍵盤之上!就像Android的效果那樣。效果圖如下:

show.gif

2. 一分鐘實現該效果:

  1. 點選這裡下載 WPAutoSpringTextViewController.h, WPAutoSpringTextViewController.m, UIResponder+FirstResponder.h, UIResponder+FirstResponder.m四個檔案到你的工程中
  2. 修改你的ViewController的父類為WPAutoSpringTextViewController

大功告成,是不是很簡單!如果想了解實現方法,請繼續閱讀。

3. 實現原理

首先,我們需要監聽鍵盤的廣播:

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

鍵盤彈出廣播中我們需要獲取鍵盤彈出的高度,鍵盤彈出的時間。

float duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGFloat keyboardHeight = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

然後我們判斷此時view需要移動的距離,這裡首先獲取firstResponder,然後判斷其是否為UITextView或UITextField類或其子類,再根據該輸入框在螢幕上的位置計算是否需要彈起view,需要則返回需要彈起的高度,不需要則為0。

- (CGFloat)shouldScrollWithKeyboardHeight:(CGFloat)keyboardHeight{
    id responder = [UIResponder currentFirstResponder];
    if([responder isKindOfClass:[UITextView class]] || [responder isKindOfClass:[UITextField class]]){
        UIView *view = responder;
        CGFloat y = [responder convertPoint:CGPointZero toView:[UIApplication sharedApplication].keyWindow].y;
        CGFloat bottom = y + view.frame.size.height;
        if(bottom > SCREEN_HEIGHT - keyboardHeight){
            return bottom - (SCREEN_HEIGHT - keyboardHeight);
        }
    }
    return 0;
}

最後當我們發現需要彈起頁面時則動畫彈起頁面:

CGFloat shouldScrollHeight = [self shouldScrollWithKeyboardHeight:keyboardHeight];
    if(shouldScrollHeight == 0){
        return;
    }
    __weak WPAutoSpringTextViewController *weakSelf = self;
    [UIView animateWithDuration:duration animations:^{
        CGRect bounds = weakSelf.view.bounds;
        weakSelf.view.bounds = CGRectMake(0, shouldScrollHeight + 10, bounds.size.width, bounds.size.height);
    }];

這裡主要的邏輯都已經完成了,點選在鍵盤覆蓋範圍內的輸入框時,介面可以自動彈起。當點選空白區域時,鍵盤自動收起,這個功能程式碼如下:

self.view.userInteractionEnabled = YES;
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClicked)]];
- (void)viewClicked{
    if(keyboardIsShowing){
        id responder = [UIResponder currentFirstResponder];
        if([responder isKindOfClass:[UITextView class]] || [responder isKindOfClass:[UITextField class]]){
            UIView *view = responder;
            [view resignFirstResponder];
        }
    }
}

好了大功告成! 完整的程式碼如下。Github地址
https://github.com/MRsummer/WPAutoSpringKeyboard

#import "WPAutoSpringTextViewController.h"
#import "UIResponder+FirstResponder.h"

#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height

@implementation WPAutoSpringTextViewController{
    BOOL keyboardIsShowing;
}

-(void)viewDidLoad{
    [super viewDidLoad];
    [self enableEditTextScroll];
    self.view.userInteractionEnabled = YES;
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewClicked)]];
}

- (void)viewClicked{
    if(keyboardIsShowing){
        id responder = [UIResponder currentFirstResponder];
        if([responder isKindOfClass:[UITextView class]] || [responder isKindOfClass:[UITextField class]]){
            UIView *view = responder;
            [view resignFirstResponder];
        }
    }
}

- (CGFloat)shouldScrollWithKeyboardHeight:(CGFloat)keyboardHeight{
    id responder = [UIResponder currentFirstResponder];
    if([responder isKindOfClass:[UITextView class]] || [responder isKindOfClass:[UITextField class]]){
        UIView *view = responder;
        CGFloat y = [responder convertPoint:CGPointZero toView:[UIApplication sharedApplication].keyWindow].y;
        CGFloat bottom = y + view.frame.size.height;
        NSLog(@"shouldScrollWithKeyboardHeight -->keyboradHeight %@, keyboradBottom %@, viewY %@, bottom %@", @(keyboardHeight), @(SCREEN_HEIGHT - keyboardHeight), @(y), @(bottom));
        if(bottom > SCREEN_HEIGHT - keyboardHeight){
            return bottom - (SCREEN_HEIGHT - keyboardHeight);
        }
    }
    return 0;
}

- (void)enableEditTextScroll{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wpKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wpKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wpKeyboardDidShow) name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wpKeyboardDidHide) name:UIKeyboardDidHideNotification object:nil];
}

- (void)wpKeyboardDidShow{
    keyboardIsShowing = YES;
}

- (void)wpKeyboardDidHide{
    keyboardIsShowing = NO;
}

- (void)wpKeyboardWillHide:(NSNotification *)note {
    float duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    __weak WPAutoSpringTextViewController *weakSelf = self;
    [UIView animateWithDuration:duration animations:^{
        CGRect bounds = weakSelf.view.bounds;
        weakSelf.view.bounds = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
    }];
}

- (void)wpKeyboardWillShow:(NSNotification *)note {
    float duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    CGFloat keyboardHeight = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    CGFloat shouldScrollHeight = [self shouldScrollWithKeyboardHeight:keyboardHeight];
    if(shouldScrollHeight == 0){
        return;
    }
    __weak WPAutoSpringTextViewController *weakSelf = self;
    [UIView animateWithDuration:duration animations:^{
        CGRect bounds = weakSelf.view.bounds;
        weakSelf.view.bounds = CGRectMake(0, shouldScrollHeight + 10, bounds.size.width, bounds.size.height);
    }];
}

@end

相關文章