對 鍵盤 事件 監聽NSNotification 處理相應頁面 變化UIKeyboardAnimation

App應用中,難免會需要用戶輸入一些相關數據。
於是就用到鍵盤。
鍵盤在iPhone和iPad中,類似是一個View的形式來顯示和隱藏。
當一個輸入框得到焦點時,系統會默認調用鍵盤事件。來顯示鍵盤;當輸入框失去焦點時,鍵盤會消失。

那麼,鍵盤事件有一下4種:

UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification;

UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification; 

UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification; 

UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification;


1.註冊鍵盤事件:

- (void) viewWillAppear:(BOOL)paramAnimated{

    [super viewDidAppear:paramAnimated];

    

    // 在通知中心註冊觀察者,並指定觀察者感興趣的事件

    

    // 鍵盤將要顯示時

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    [center addObserver:self

              selector:@selector(handleKeyboardWillShow:)

                   name:UIKeyboardWillShowNotification

                object:nil];

    

    // 鍵盤將要隱藏時

    [center addObserver:self

              selector:@selector(handleKeyboardWillHide:)

                   name:UIKeyboardWillHideNotification

                object:nil];

   

}


2.鍵盤事件執行的方法:

// 鍵盤出現時,調用該方法

- (void) handleKeyboardWillShow:(NSNotification *)paramNotification{

    NSDictionary *userInfo = [paramNotification userInfo];

    NSValue *animationCurveObject =[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey];

    NSValue *animationDurationObject =[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSValue *keyboardEndRectObject =[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

    NSUInteger animationCurve = 0;

    double animationDuration = 0.0f;

    CGRect keyboardEndRect = CGRectMake(0, 0, 0, 0);

    [animationCurveObject getValue:&animationCurve];

    [animationDurationObject getValue:&animationDuration];

    [keyboardEndRectObject getValue:&keyboardEndRect];

    

    [UIView beginAnimations:@"changeTableViewContentInset" context:NULL];

    

    [UIView setAnimationDuration:animationDuration];

    [UIView setAnimationCurve:(UIViewAnimationCurve)animationCurve];

    

    UIWindow *window = [[[UIApplication sharedApplication] delegate] window];// 獲得window

    // 得到window.frame和鍵盤frame的交集

    CGRect intersectionOfKeyboardRectAndWindowRect = CGRectIntersection(window.frame, keyboardEndRect);

    CGFloat bottomInset = intersectionOfKeyboardRectAndWindowRect.size.height;

    self.myTableView.contentInset = UIEdgeInsetsMake(0.0f,0.0f,bottomInset,0.0f);

    NSIndexPath *indexPathOfOwnerCell = nil;

    // 保證得到焦點的UITextField(文本框)也顯示在屏幕上

    NSInteger numberOfCells = [self.myTableView.dataSource tableView:self.myTableView

                                              numberOfRowsInSection:0];

    

    // 循環,並且得到獲得焦點的UITextField(文本框)所在的UITableViewCell中的NSIndexPath信息,並滾動TableView到相應的位置

    for (NSInteger counter = 0;counter < numberOfCells;counter++){

       NSIndexPath *indexPath = [NSIndexPath indexPathForRow:counter inSection:0];

       UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];

        UITextField *textField = (UITextField *)cell.accessoryView;

       if ([textField isKindOfClass:[UITextField class]] == NO){

           continue;

        }

       if ([textField isFirstResponder]){

            indexPathOfOwnerCell = indexPath;

           break;

        }

    }

    

    [UIView commitAnimations];

    

    // 滾動TableView到相應的位置

    if (indexPathOfOwnerCell != nil){

        [self.myTableView scrollToRowAtIndexPath:indexPathOfOwnerCell

                                atScrollPosition:UITableViewScrollPositionMiddle

                                       animated:YES];

    }

}


// 鍵盤將要消失時,執行該方法

- (void) handleKeyboardWillHide:(NSNotification *)paramNotification{

    // 比較兩個EdgeInsets是否相等

    if (UIEdgeInsetsEqualToEdgeInsets(self.myTableView.contentInset, UIEdgeInsetsZero)){

        // 無需設置TableViewcontentInset

       return;

    }

    NSDictionary *userInfo = [paramNotification userInfo];

    NSValue *animationCurveObject =[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey];

    NSValue *animationDurationObject =[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSValue *keyboardEndRectObject =[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

    NSUInteger animationCurve = 0;

    double animationDuration = 0.0f;

    CGRect keyboardEndRect = CGRectMake(0, 0, 0, 0);

    [animationCurveObject getValue:&animationCurve];

    [animationDurationObject getValue:&animationDuration];

    [keyboardEndRectObject getValue:&keyboardEndRect];

    

    [UIView beginAnimations:@"changeTableViewContentInset" context:NULL];

    [UIView setAnimationDuration:animationDuration];

    [UIView setAnimationCurve:(UIViewAnimationCurve)animationCurve];

    self.myTableView.contentInset = UIEdgeInsetsZero;

    [UIView commitAnimations];

}


3.取消鍵盤事件

// 關於觀察者,什麼時候添加?什麼時候移除?

// 添加應該在頁面載入後,一般是:viewDidLoadviewWillAppear方法中。

// 移除應該在viewWillDisappear方法中。因爲,應該養成這麼一個好習慣:當某個ViewController不在屏幕上顯示時,應該及時將觀察者移除。


- (void) viewWillDisappear:(BOOL)paramAnimated{

    [super viewDidDisappear:paramAnimated];

    // 移除觀察者,當移除觀察者時,觀察者所註冊的觀察事件也會被移除。

    // 從通知中心移除某個通知觀察者的所有通知項。換句話說:將觀察者註冊的所有通知項從通知中心移除。

    // 當然,也可以使用 removeObserver:name:object:方法,來單個移除。

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}


4.小技巧

隱藏鍵盤,還有個方法

// 當點擊鍵盤Return按鈕時,將觸發該方法

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

    

    [textField resignFirstResponder];// 放棄第一響應者。

    

    return YES;

}


最後,附上完整源代碼:

MoreViewController.h

#import


@interface MoreViewController : UIViewController<</span>UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate>{


}


@property (nonatomic, retain) UITableView *myTableView;


@end


MoreViewController.m

#import "MoreViewController.h"


@implementation MoreViewController

@synthesize myTableView;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        

        // Custom initialization

    }

    return self;

}


- (void)dealloc{

    [super dealloc];

}




- (void)viewDidLoad{

    [super viewDidLoad];

    

    self.view.backgroundColor = [UIColor whiteColor];

    

    self.myTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];

    [self.myTableView setDataSource:self];

    [self.myTableView setDelegate:self];

    self.myTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:self.myTableView];

   


}


// 當點擊鍵盤Return按鈕時,將觸發該方法

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

    

    [textField resignFirstResponder];// 放棄第一響應者。

    

    return YES;

}


#pragma mark- UITableViewDataSource


- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{

    return 1;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    

    return 100;

}


- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell *result = nil;

    static NSString *CellIdentifier = @"CellIdentifier";

    result = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (result == nil){

        result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        result.selectionStyle = UITableViewCellSelectionStyleNone;

    }

    result.textLabel.text = [NSString stringWithFormat: @"Cell %ld", (long)indexPath.row];

    CGRect accessoryRect = CGRectMake(0.0f, 0.0f,150.0f,31.0f);

    UITextField *accesssory = [[UITextField alloc] initWithFrame:accessoryRect];

    accesssory.borderStyle = UITextBorderStyleRoundedRect;

    accesssory.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;

    accesssory.placeholder = @"Enter Text";

    accesssory.delegate = self;

    result.accessoryView = accesssory;

    return result;

}




- (void)viewDidUnload{

    [self setMyTableView:nil];

    [super viewDidUnload];


}


- (void) viewWillAppear:(BOOL)paramAnimated{

    [super viewDidAppear:paramAnimated];

    

    // 在通知中心註冊觀察者,並指定觀察者感興趣的事件

    

    // 鍵盤將要顯示時

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    [center addObserver:self

              selector:@selector(handleKeyboardWillShow:)

                   name:UIKeyboardWillShowNotification

                object:nil];

    

    // 鍵盤將要隱藏時

    [center addObserver:self

              selector:@selector(handleKeyboardWillHide:)

                   name:UIKeyboardWillHideNotification

                object:nil];

   

}



// 關於觀察者,什麼時候添加?什麼時候移除?

// 添加應該在頁面載入後,一般是:viewDidLoadviewWillAppear方法中。

// 移除應該在viewWillDisappear方法中。因爲,應該養成這麼一個好習慣:當某個ViewController不在屏幕上顯示時,應該及時將觀察者移除。


- (void) viewWillDisappear:(BOOL)paramAnimated{

    [super viewDidDisappear:paramAnimated];

    // 移除觀察者,當移除觀察者時,觀察者所註冊的觀察事件也會被移除。

    // 從通知中心移除某個通知觀察者的所有通知項。換句話說:將觀察者註冊的所有通知項從通知中心移除。

    // 當然,也可以使用 removeObserver:name:object:方法,來單個移除。

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}


// 鍵盤出現時,調用該方法

- (void) handleKeyboardWillShow:(NSNotification *)paramNotification{

    NSDictionary *userInfo = [paramNotification userInfo];

    NSValue *animationCurveObject =[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey];

    NSValue *animationDurationObject =[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSValue *keyboardEndRectObject =[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

    NSUInteger animationCurve = 0;

    double animationDuration = 0.0f;

    CGRect keyboardEndRect = CGRectMake(0, 0, 0, 0);

    [animationCurveObject getValue:&animationCurve];

    [animationDurationObject getValue:&animationDuration];

    [keyboardEndRectObject getValue:&keyboardEndRect];

    

    [UIView beginAnimations:@"changeTableViewContentInset" context:NULL];

    

    [UIView setAnimationDuration:animationDuration];

    [UIView setAnimationCurve:(UIViewAnimationCurve)animationCurve];

    

    UIWindow *window = [[[UIApplication sharedApplication] delegate] window];// 獲得window

    // 得到window.frame和鍵盤frame的交集

    CGRect intersectionOfKeyboardRectAndWindowRect = CGRectIntersection(window.frame, keyboardEndRect);

    CGFloat bottomInset = intersectionOfKeyboardRectAndWindowRect.size.height;

    self.myTableView.contentInset = UIEdgeInsetsMake(0.0f,0.0f,bottomInset,0.0f);

    NSIndexPath *indexPathOfOwnerCell = nil;

    // 保證得到焦點的UITextField(文本框)也顯示在屏幕上

    NSInteger numberOfCells = [self.myTableView.dataSource tableView:self.myTableView

                                              numberOfRowsInSection:0];

    

    // 循環,並且得到獲得焦點的UITextField(文本框)所在的UITableViewCell中的NSIndexPath信息,並滾動TableView到相應的位置

    for (NSInteger counter = 0;counter < numberOfCells;counter++){

       NSIndexPath *indexPath = [NSIndexPath indexPathForRow:counter inSection:0];

       UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];

        UITextField *textField = (UITextField *)cell.accessoryView;

       if ([textField isKindOfClass:[UITextField class]] == NO){

           continue;

        }

       if ([textField isFirstResponder]){

            indexPathOfOwnerCell = indexPath;

           break;

        }

    }

    

    [UIView commitAnimations];

    

    // 滾動TableView到相應的位置

    if (indexPathOfOwnerCell != nil){

        [self.myTableView scrollToRowAtIndexPath:indexPathOfOwnerCell

                                atScrollPosition:UITableViewScrollPositionMiddle

                                       animated:YES];

    }

}


// 鍵盤將要消失時,執行該方法

- (void) handleKeyboardWillHide:(NSNotification *)paramNotification{

    // 比較兩個EdgeInsets是否相等

    if (UIEdgeInsetsEqualToEdgeInsets(self.myTableView.contentInset, UIEdgeInsetsZero)){

        // 無需設置TableViewcontentInset

       return;

    }

    NSDictionary *userInfo = [paramNotification userInfo];

    NSValue *animationCurveObject =[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey];

    NSValue *animationDurationObject =[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey];

    NSValue *keyboardEndRectObject =[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

    NSUInteger animationCurve = 0;

    double animationDuration = 0.0f;

    CGRect keyboardEndRect = CGRectMake(0, 0, 0, 0);

    [animationCurveObject getValue:&animationCurve];

    [animationDurationObject getValue:&animationDuration];

    [keyboardEndRectObject getValue:&keyboardEndRect];

    

    [UIView beginAnimations:@"changeTableViewContentInset" context:NULL];

    [UIView setAnimationDuration:animationDuration];

    [UIView setAnimationCurve:(UIViewAnimationCurve)animationCurve];

    self.myTableView.contentInset = UIEdgeInsetsZero;

    [UIView commitAnimations];

}



#pragma mark - 旋轉支持

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

{

//    return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);

    return YES;

}


-(BOOL)shouldAutorotate

{

    return YES;

}


-(NSInteger)supportedInterfaceOrientations

{

//    return UIInterfaceOrientationMaskLandscape;

    return UIInterfaceOrientationMaskAll;

}




@end



希望對你有所幫助!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章