UITextField滑動防止被鍵盤擋住 終極解決方案
阿新 • • 發佈:2019-01-22
原文地址: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原始碼
- //
- // AutoScrollView.h
- // AutoScrollView
- //
- // Created by KindAzrael on 13-2-18.
- // Copyright (c) 2013年 KindAzrael. All rights reserved.
- //
-
#import <UIKit/UIKit.h>
- @interface AutoScrollView : UIScrollView
- @property(assign, nonatomic) CGPoint previousOffset;
- @end
- //
- // AutoScrollView.m
- // AutoScrollView
- //
- // Created by KindAzrael on 13-2-18.
- // Copyright (c) 2013年 KindAzrael. All rights reserved.
- //
- #import "AutoScrollView.h"
- @interface AutoScrollView ()
-
// add the keybord notification
- - (void)setup;
- // remove the keybord notification
- - (void)tearDown;
- - (void)keyboardWillShow:(NSNotification *)notification;
- - (void)keyboardWillHide:(NSNotification *)notification;
- @end
- @implementation AutoScrollView
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- [self setup];
- }
- return self;
- }
- - (void)awakeFromNib {
- [self setup];
- self.contentSize = CGSizeMake(320, 700);
- }
- - (void)dealloc {
- [self tearDown];
- }
- // hide keybord when touch croll view
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- [super touchesBegan:touches withEvent:event];
- [self endEditing:YES];
- }
- - (void)setup {
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
- }
- - (void)tearDown {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- // scroll contentOffset when keybord will show
- - (void)keyboardWillShow:(NSNotification *)notification {
- self.previousOffset = self.contentOffset;
- NSDictionary *userInfo = [notification userInfo];
- // get keyboard rect in windwo coordinate
- CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- // convert keyboard rect from window coordinate to scroll view coordinate
- keyboardRect = [self convertRect:keyboardRect fromView:nil];
- // get keybord anmation duration
- NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
- // get first responder textfield
- UIView *currentResponder = [self findFirstResponderBeneathView:self];
- if (currentResponder != nil) {
- // convert textfield left bottom point to scroll view coordinate
- CGPoint point = [currentResponder convertPoint:CGPointMake(0, currentResponder.frame.size.height) toView:self];
- // 計算textfield左下角和鍵盤上面20畫素 之間是不是差值
- float scrollY = point.y - (keyboardRect.origin.y - 20);
- if (scrollY > 0) {
- [UIView animateWithDuration:animationDuration animations:^{
- //移動textfield到鍵盤上面20個畫素
- self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + scrollY);
- }];
- }
- }
- self.scrollEnabled = NO;
- }
- // roll back content offset
- -(void)keyboardWillHide:(NSNotification *)notification {
- NSDictionary *userInfo = [notification userInfo];
- NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
- [UIView animateWithDuration:animationDuration animations:^{
- self.contentOffset = self.previousOffset;
- }];
- self.scrollEnabled = YES;
- }
- - (UIView*)findFirstResponderBeneathView:(UIView*)view {
- // Search recursively for first responder
- for ( UIView *childView in view.subviews ) {
- if ( [childView respondsToSelector:@selector(isFirstResponder)] && [childView isFirstResponder] ) return childView;
- UIView *result = [self findFirstResponderBeneathView:childView];
- if ( result ) return result;
- }
- return nil;
- }
- @end
效果