定制scrollView来处理自动显示与隐藏键盘

简介:
//
//  HYBKeyboardScrollView.h
//  HomeLinkProject
//
//  Created by huangyibiao on 14-6-3.
//  Copyright (c) 2014年 huangyibiao. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol HYBKeyboardScrollViewDelegate <NSObject>

- (void)keyboardWillHide;

@end

/*!
 * @brief 继承于UIScrollView,添加解决键盘自动隐藏的功能
 * @author huangyibiao
 */
@interface HYBKeyboardScrollView : UIScrollView

// 键盘将要键盘的代理
@property (nonatomic, weak) id<HYBKeyboardScrollViewDelegate> keyboardHideDelegate;

@end


//
//  HYBKeyboardScrollView.m
//  HomeLinkProject
//
//  Created by huangyibiao on 14-6-3.
//  Copyright (c) 2014年 huangyibiao. All rights reserved.
//

#import "HYBKeyboardScrollView.h"

@interface HYBKeyboardScrollView ()

/*!
 * @brief 上一次的偏移量
 */
@property(nonatomic, assign) CGPoint previousOffset;

// 添加、移除对键盘的监听通知
- (void)addKeyboardNotifications;
- (void)removeKeyboardNotifications;

// 键盘出现、隐藏的通知回调
- (void)keyboardWillShow:(NSNotification *)notification;
- (void)keyboardWillHide:(NSNotification *)notification;
@end

@implementation HYBKeyboardScrollView

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self addKeyboardNotifications];
    }
    return self;
}

- (void)awakeFromNib {
    [self addKeyboardNotifications];
    self.contentSize = CGSizeMake(320, 700);
    return;
}

- (void)dealloc {
    [self removeKeyboardNotifications];
    return;
}

- (void)addKeyboardNotifications {
    [kNotificationCenter addObserver:self
                            selector:@selector(keyboardWillShow:)
                                name:UIKeyboardWillShowNotification
                              object:nil];
    [kNotificationCenter addObserver:self
                            selector:@selector(keyboardWillHide:)
                                name:UIKeyboardWillHideNotification
                              object:nil];
    return;
}

- (void)removeKeyboardNotifications {
    [kNotificationCenter removeObserver:self
                                name:UIKeyboardWillShowNotification
                              object:nil];
    [kNotificationCenter removeObserver:self
                                name:UIKeyboardWillHideNotification
                              object:nil];
    return;
}

// 点击滚动视图时隐藏键盘
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    [self endEditing:YES];
    if ([self.keyboardHideDelegate respondsToSelector:@selector(keyboardWillHide)]) {
        [self.keyboardHideDelegate keyboardWillHide];
    }
    return;
}

// 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;
    return;
}

// 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;
    if ([self.keyboardHideDelegate respondsToSelector:@selector(keyboardWillHide)]) {
        [self.keyboardHideDelegate keyboardWillHide];
    }
    return;
}

- (UIView *)findFirstResponderBeneathView:(UIView *)view {
    // 递归查找第一响应者
    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


目录
相关文章
|
21天前
toolbar设置返回键以及点击事件
toolbar设置返回键以及点击事件
9 0
toolbar改变返回按钮方法
toolbar改变返回按钮方法
130 0
|
iOS开发
iOS ScrollView嵌套tableview左右滑动时禁止上下滑动
iOS ScrollView嵌套tableview左右滑动时禁止上下滑动
1419 0
|
Android开发
Android RecyclerView滑动到底部/上拉/上拉见底自动加载更多实现以及点击/长按事件处理
Android RecyclerView滑动到底部/上拉/上拉见底自动加载更多实现以及点击/长按事件处理 Android RecyclerView下拉加载更多有Android谷歌官方的实现,实现的方式是通过SwipeRefreshLayout把RecyclerView包裹起来,然后就可以通过SwipeRefreshLayout的回调接口实现下拉刷新功能。
1792 0
|
Web App开发 JavaScript 测试技术
|
Web App开发 iOS开发 API
教你如何强制显示一个竖屏的不能侧滑返回的SFSafariViewController
强制让控制器竖屏显示 - (BOOL)shouldAutorotate { return NO; } - (UIInterfaceOrientationMask)supportedInterfaceOrientations { ret...
1295 0
|
Android开发
让 Toolbar 随着 RecyclerView 的滚动而显示/隐藏
本文讲的是让 Toolbar 随着 RecyclerView 的滚动而显示/隐藏,在这篇文章中,我们将看到如何实现像Google+ 应用程序一样,当列表下滑时,Toolbar和FAB(包括其他的View)隐藏;当列表上滑时,Toolbar和FAB(包括其他的View)显示的效果;这种效果在Material Design Checklist提到过.
1837 0
ScrollView嵌套EditText联带滑动的解决办法
本篇文章的相关内容需结合上文:从ScrollView嵌套EditText的滑动事件冲突分析触摸事件的分发机制以及TextView的简要实现和冲突的解决办法 在说完了如何解决ScrollView嵌套EditText的滑动事件冲突之后,我们接下来说一下如何实现它们两者之间的联带滑动。
1043 0