1. 程式人生 > >UITextField滑動防止被鍵盤擋住 終極解決方案

UITextField滑動防止被鍵盤擋住 終極解決方案

原文地址:http://blog.csdn.net/kindazrael/article/details/8592866

這個是利用第三方開源框架 autoscroll 簡單實現

autoscroll 開源中國下載地址:http://www.oschina.net/p/Auto-Scroll

問題:當螢幕下方有textfield時會被彈出的鍵盤擋住,使用者體驗不太好。

堅決方法:使用scroll view 當textfield成為first responder時 將textfield滑動到鍵盤上面

網上這方面的解決方法有很多,但是都不夠完美,比如無法真確處理手持方向改變時keybord高度不一樣的情況,無法相容iPad下鍵盤和iPhone高度不一樣,

動畫不和諧,實現過於複雜等等問題。 現在我分享的一個簡單易懂又比較完美的方法。

AutoScrollView類自動的實現了這一特性,要整合這個功能,只要在xib中將ScrolView的Customer class設定成AutoScrollView就可以了,非常簡單容易。


下面是AutoScrollView原始碼

  1. //
  2. //  AutoScrollView.h
  3. //  AutoScrollView
  4. //
  5. //  Created by KindAzrael on 13-2-18.
  6. //  Copyright (c) 2013年 KindAzrael. All rights reserved.
  7. //
  8. #import <UIKit/UIKit.h>
  9. @interface AutoScrollView : UIScrollView  
  10. @property(assign, nonatomic) CGPoint previousOffset;  
  11. @end  

  1. //
  2. //  AutoScrollView.m
  3. //  AutoScrollView
  4. //
  5. //  Created by KindAzrael on 13-2-18.
  6. //  Copyright (c) 2013年 KindAzrael. All rights reserved.
  7. //
  8. #import "AutoScrollView.h"
  9. @interface AutoScrollView ()  
  10. // add the keybord notification 
  11. - (void)setup;  
  12. // remove the keybord notification
  13. - (void)tearDown;  
  14. - (void)keyboardWillShow:(NSNotification *)notification;  
  15. - (void)keyboardWillHide:(NSNotification *)notification;  
  16. @end  
  17. @implementation AutoScrollView  
  18. - (id)initWithFrame:(CGRect)frame  
  19. {  
  20.     self = [super initWithFrame:frame];  
  21.     if (self) {  
  22.         [self setup];  
  23.     }  
  24.     return self;  
  25. }  
  26. - (void)awakeFromNib {  
  27.     [self setup];  
  28.     self.contentSize = CGSizeMake(320, 700);  
  29. }  
  30. - (void)dealloc {  
  31.     [self tearDown];  
  32. }  
  33. // hide keybord when touch croll view
  34. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  35.     [super touchesBegan:touches withEvent:event];  
  36.     [self endEditing:YES];  
  37. }  
  38. - (void)setup {  
  39.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];  
  40.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];  
  41. }  
  42. - (void)tearDown {  
  43.     [[NSNotificationCenter defaultCenter] removeObserver:self];  
  44. }  
  45. // scroll contentOffset when keybord will show 
  46. - (void)keyboardWillShow:(NSNotification *)notification {  
  47.     self.previousOffset = self.contentOffset;  
  48.     NSDictionary *userInfo = [notification userInfo];  
  49.     // get keyboard rect in windwo coordinate 
  50.     CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];  
  51.     // convert keyboard rect from window coordinate to scroll view coordinate
  52.     keyboardRect = [self convertRect:keyboardRect fromView:nil];  
  53.     // get keybord anmation duration
  54.     NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];  
  55.     // get first responder textfield 
  56.     UIView *currentResponder = [self findFirstResponderBeneathView:self];  
  57.     if (currentResponder != nil) {  
  58.         // convert textfield left bottom point to scroll view coordinate
  59.         CGPoint point = [currentResponder convertPoint:CGPointMake(0, currentResponder.frame.size.height) toView:self];  
  60.         // 計算textfield左下角和鍵盤上面20畫素 之間是不是差值
  61.         float scrollY = point.y - (keyboardRect.origin.y - 20);  
  62.         if (scrollY > 0) {  
  63.             [UIView animateWithDuration:animationDuration animations:^{  
  64.                 //移動textfield到鍵盤上面20個畫素
  65.                 self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + scrollY);  
  66.             }];  
  67.         }  
  68.     }  
  69.     self.scrollEnabled = NO;  
  70. }  
  71. // roll back content offset
  72. -(void)keyboardWillHide:(NSNotification *)notification {  
  73.     NSDictionary *userInfo = [notification userInfo];  
  74.     NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];  
  75.     [UIView animateWithDuration:animationDuration animations:^{  
  76.         self.contentOffset = self.previousOffset;  
  77.     }];  
  78.     self.scrollEnabled = YES;  
  79. }  
  80. - (UIView*)findFirstResponderBeneathView:(UIView*)view {  
  81.     // Search recursively for first responder
  82.     for ( UIView *childView in view.subviews ) {  
  83.         if ( [childView respondsToSelector:@selector(isFirstResponder)] && [childView isFirstResponder] ) return childView;  
  84.         UIView *result = [self findFirstResponderBeneathView:childView];  
  85.         if ( result ) return result;  
  86.     }  
  87.     return nil;  
  88. }  
  89. @end  

效果