天天看点

使用第三方IQKeyboardManager处理键盘问题

这个库的下载地址:https://github.com/hackiftekhar/IQKeyboardManager

IQKeyboardManager 的初始化

当 IQKeyboardManager 初始化的时候,它做了这么几件事情:

1. 监听有关键盘的通知q

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];

2. 注册与 UITextField 以及 UITextView 有关的通知

[self registerTextFieldViewClass:[UITextField class]

didBeginEditingNotificationName:UITextFieldTextDidBeginEditingNotification

didEndEditingNotificationName:UITextFieldTextDidEndEditingNotification];

[self registerTextFieldViewClass:[UITextView class]

didBeginEditingNotificationName:UITextViewTextDidBeginEditingNotification

didEndEditingNotificationName:UITextViewTextDidEndEditingNotification];

  • 调用的方法将通知绑定到了 textFieldViewDidBeginEditing: 和 textFieldViewDidEndEditing: 方法上

- (void)registerTextFieldViewClass:(nonnull Class)aClass

didBeginEditingNotificationName:(nonnull NSString *)didBeginEditingNotificationName

didEndEditingNotificationName:(nonnull NSString *)didEndEditingNotificationName {

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldViewDidBeginEditing:) name:didBeginEditingNotificationName object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldViewDidEndEditing:) name:didEndEditingNotificationName object:nil];

}

3. 初始化一个 UITapGestureRecognizer,在点击 UITextField 对应的 UIWindow 的时候,收起键盘

strongSelf.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapRecognized:)];

- (void)tapRecognized:(UITapGestureRecognizer*)gesture {

if (gesture.state == UIGestureRecognizerStateEnded)

[self resignFirstResponder];

}

4. 初始化一些默认属性,例如键盘距离、覆写键盘的样式等

strongSelf.animationDuration = 0.25;

strongSelf.animationCurve = UIViewAnimationCurveEaseInOut;

[self setKeyboardDistanceFromTextField:10.0];

[self setShouldPlayInputClicks:YES];

[self setShouldResignOnTouchOutside:NO];

[self setOverrideKeyboardAppearance:NO];

[self setKeyboardAppearance:UIKeyboardAppearanceDefault];

[self setEnableAutoToolbar:YES];

[self setPreventShowingBottomBlankSpace:YES];

[self setShouldShowTextFieldPlaceholder:YES];

[self setToolbarManageBehaviour:IQAutoToolbarBySubviews];

[self setLayoutIfNeededOnUpdate:NO];

5. 设置不需要解决键盘遮挡问题的类

strongSelf.disabledDistanceHandlingClasses = [[NSMutableSet alloc] initWithObjects:[UITableViewController class], nil];

strongSelf.enabledDistanceHandlingClasses = [[NSMutableSet alloc] init];

strongSelf.disabledToolbarClasses = [[NSMutableSet alloc] init];

strongSelf.enabledToolbarClasses = [[NSMutableSet alloc] init];

strongSelf.toolbarPreviousNextAllowedClasses = [[NSMutableSet alloc] initWithObjects:[UITableView class],[UICollectionView class],[IQPreviousNextView class], nil];

strongSelf.disabledTouchResignedClasses = [[NSMutableSet alloc] init];

strongSelf.enabledTouchResignedClasses = [[NSMutableSet alloc] init];

整个初始化方法大约有几十行的代码,在这里就不再展示整个方法的全部代码了。

基于通知的解决方案

在这里,我们以 UITextField 为例,分析方法的调用流程。

在初始化方法中,我们注册了很多的通知,包括键盘的出现和隐藏,UITextField 开始编辑与结束编辑。

UIKeyboardWillShowNotification

UIKeyboardWillHideNotification

UIKeyboardDidHideNotification

UITextFieldTextDidBeginEditingNotification

UITextFieldTextDidEndEditingNotification

在这些通知响应时,会执行以下的方法:

| Notification | Selector | |:-:|:-:| | UIKeyboardWillShowNotification | @selector(keyboardWillShow:)| | UIKeyboardWillHideNotification | @selector(keyboardWillHide:) | | UIKeyboardDidHideNotification | @selector(keyboardDidHide:) | |UITextFieldTextDidBeginEditingNotification|@selector(textFieldViewDidBeginEditing:)| |UITextFieldTextDidEndEditingNotification|@selector(textFieldViewDidEndEditing:)|

整个解决方案其实都是基于 iOS 中的通知系统的;在事件发生时,调用对应的方法做出响应。

这个库是一个单例,它一旦生效,全项目任何界面都有效。让它生效的代码可以写在任意位置,我写在AppDelegate里。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    IQKeyboardManager *manager = [IQKeyboardManager sharedManager];
    manager.enable = YES;
    manager.shouldResignOnTouchOutside = YES;
    manager.shouldToolbarUsesTextFieldTintColor = YES;
    manager.enableAutoToolbar = NO;
    
    return YES;
}
           

enable控制整个功能是否启用。

shouldResignOnTouchOutside控制点击背景是否收起键盘。

shouldToolbarUsesTextFieldTintColor 控制键盘上的工具条文字颜色是否用户自定义。

enableAutoToolbar控制是否显示键盘上的工具条。

以上设置,就启用了这个库。

使用方法,代码如下:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) IQKeyboardReturnKeyHandler    *returnKeyHandler;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.returnKeyHandler = [[IQKeyboardReturnKeyHandler alloc] initWithViewController:self];
    self.returnKeyHandler.lastTextFieldReturnKeyType = UIReturnKeyDone;
    self.returnKeyHandler.toolbarManageBehaviour = IQAutoToolbarBySubviews;
}

- (void)dealloc
{
    self.returnKeyHandler = nil;
}

@end           

设置returnKeyHandler,可以点击键盘上的next键,自动跳到下一个输入框。最后一个输入框点击done自动收起键盘。

运行后,可以看到输入框随着键盘的弹出自动上下浮动。点击背景,键盘收起。全自动了。

这个库默认支持UITextField、UITextView、UIWebView、UIScrollView、UITableView、UICollectionView

最后要注意一点,它可以自动计算多个textField之间的先后顺序,排列依据是看addSubView的先后顺序。