Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

UITextField滑动防止被键盘挡住 终极解决方案

$
0
0

问题:当屏幕下方有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


效果


作者:KindAzrael 发表于2013-2-20 0:22:53 原文链接
阅读:92 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>