iOS中UITextField控件和UITextView控件经常需要对键盘做弹起和退出动作,一般使用的是becomeFirstResponder和resignFirstResponder方法,但是这样也有明显的缺点,就是会在键盘的弹起退出过程中经常出现黑边,或者断层,导致效果很不好看,在网上找了些资料,自己做了一个自定义的输入框来解决这个问题,效果类似于微信和QQ的聊天框。
不废话,直接上代码,另外做了一个demo,链接为https://github.com/didashao/KLCPopKeyBoard
KLCPopKeyBoard.h
#import
@class KLCPopKeyBoard;
@protocol KLCPopKeyBoardDelegate
- (void)popKeyBoard:(KLCPopKeyBoard *)popKeyBoard didClickSend:(BOOL)didClickSend;
- (void)popKeyBoardHide;
- (void)popKeyBoardShow;
@end
@interface KLCPopKeyBoard : UIView
@property (nonatomic, weak) id delegate;
@property (nonatomic, copy) NSString *content;//输入框内容
@property (nonatomic, copy) NSString *placeholder;
- (instancetype)initWithPlaceholder:(NSString *)placeholder buttonTitle:(NSString *)buttonTitle;
//成对使用,可以保证一直在屏幕中出现
- (void)viewWillAppear;
- (void)viewWillDisAppear;
//成对使用,可以保证单次显示
- (void)show;
- (void)hide;
//推出键盘和退出键盘
- (void)pushKeyboard;
- (void)hideKeyboard;
@end
KLCPopKeyBoard.m
#import "KLCPopKeyBoard.h"
#define KeyBoardHeight 44
#define FullScreen_Height [[UIScreen mainScreen] bounds].size.height
#define FullScreen_Width [[UIScreen mainScreen] bounds].size.width
static inline UIViewAnimationOptions NgAnimationOptionsWithCurve(UIViewAnimationCurve curve)
{
switch (curve) {
case UIViewAnimationCurveEaseInOut:
return UIViewAnimationOptionCurveEaseInOut;
case UIViewAnimationCurveEaseIn:
return UIViewAnimationOptionCurveEaseIn;
case UIViewAnimationCurveEaseOut:
return UIViewAnimationOptionCurveEaseOut;
case UIViewAnimationCurveLinear:
return UIViewAnimationOptionCurveLinear;
}
return 0;
}
@interface KLCPopKeyBoard()
{
UIView *_bgView;
UITextField *_field;
UIButton *_button;
NSString *_placeholder;
NSString *_buttonTitle;
//BOOL _willHidden;
}
@end
@implementation KLCPopKeyBoard
- (instancetype)init
{
self = [super init];
if (self) {
_placeholder = @"";
_buttonTitle = @"发送";
[self setupUI];
}
return self;
}
- (instancetype)initWithPlaceholder:(NSString *)placeholder buttonTitle:(NSString *)buttonTitle
{
self = [super init];
if (self) {
_placeholder = placeholder;
_buttonTitle = buttonTitle;
[self setupUI];
}
return self;
}
- (void)setupUI
{
self.frame = CGRectMake(0, FullScreen_Height - KeyBoardHeight, FullScreen_Width, KeyBoardHeight);
_bgView = [[UIView alloc]init];
_bgView.frame = self.bounds;
_bgView.backgroundColor = [UIColor whiteColor];
[self addSubview:_bgView];
UIView *line = [[UIView alloc]init];
line.frame = CGRectMake(0, 0, FullScreen_Width, 0.5);
line.backgroundColor = [UIColor blackColor];
[_bgView addSubview:line];
CGFloat height = 30;
CGFloat topMargin = (KeyBoardHeight - height)/2;
CGFloat leftMargin = 10;
CGFloat buttonWidth = 44;
CGFloat buttonHeight = 30;
_field = [[UITextField alloc]init];
_field.frame = CGRectMake(leftMargin, topMargin, FullScreen_Width - leftMargin*3 - buttonWidth, height);
_field.backgroundColor = [UIColor whiteColor];
_field.textColor = [UIColor blackColor];
_field.font = [UIFont systemFontOfSize:14];
_field.returnKeyType = UIReturnKeyDone;
_field.layer.cornerRadius = 3;
_field.clipsToBounds = YES;
_field.delegate = self;
_field.placeholder = _placeholder;
[_bgView addSubview:_field];
_button = [[UIButton alloc]init];
_button.frame = CGRectMake(CGRectGetMaxX(_field.frame)+leftMargin, topMargin, buttonWidth, buttonHeight);
[_button setTitle:_buttonTitle forState:UIControlStateNormal];
_button.titleLabel.font = [UIFont systemFontOfSize:14];
_button.backgroundColor = [UIColor yellowColor];
[_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_button.layer.cornerRadius = 3;
_button.clipsToBounds = YES;
[_button addTarget:self action:@selector(didClickButton:) forControlEvents:UIControlEventTouchUpInside];
[_bgView addSubview:_button];
}
#pragma mark -发送
- (void)didClickButton:(UIButton *)btn
{
_content = _field.text;
if ([_delegate respondsToSelector:@selector(popKeyBoard:didClickSend:)]) {
[_delegate popKeyBoard:self didClickSend:YES];
_field.text = nil;
[self hideKeyboard];
}
}
- (void)setPlaceholder:(NSString *)placeholder
{
_placeholder = placeholder;
_field.placeholder = placeholder;
}
#pragma mark - 展示控制
- (void)viewWillAppear
{
[self show];
}
- (void)viewWillDisAppear
{
[self hide];
}
- (void)show
{
dispatch_async(dispatch_get_main_queue(), ^{
for (UIView *view in [UIApplication sharedApplication].keyWindow.subviews) {
if ([view isKindOfClass:[KLCPopKeyBoard class]]) {
return;
}
}
[[UIApplication sharedApplication].keyWindow addSubview:self];
[[UIApplication sharedApplication].keyWindow bringSubviewToFront:self];
});
}
-(void)hide
{
dispatch_async(dispatch_get_main_queue(), ^{
[self removeFromSuperview];
});
/*
if ([_field isFirstResponder]) {
_willHidden = YES;
[self hideKeyboard];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self removeFromSuperview];
});
}*/
}
#pragma mark - 推出和退出键盘
- (void)pushKeyboard
{
if (![_field isFirstResponder]) {
[_field becomeFirstResponder];
if ([_delegate respondsToSelector:@selector(popKeyBoardShow)]) {
// [_delegate popKeyBoardShow];
}
}
}
- (void)hideKeyboard
{
if ([_field isFirstResponder]) {
[_field resignFirstResponder];
if ([_delegate respondsToSelector:@selector(popKeyBoardHide)]) {
[_delegate popKeyBoardHide];
}
}
}
#pragma mark - 键盘监听
- (void)startListenKeyboard
{
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardDidShow:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardDidHide:)
name:UIKeyboardDidHideNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardDidChangeFrame:)
name:UIKeyboardDidChangeFrameNotification object:nil];
}
- (void)endListenKeyboard
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)onKeyboardWillShow:(NSNotification *)note {
}
- (void)onKeyboardDidShow:(NSNotification *)note {
}
- (void)onKeyboardWillHide:(NSNotification *)note {
if ([_delegate respondsToSelector:@selector(popKeyBoardHide)]) {
[_delegate popKeyBoardHide];
}
}
- (void)onKeyboardDidHide:(NSNotification *)note {
}
- (void)onKeyboardWillChangeFrame:(NSNotification *)note {
//Log("%@",note.userInfo);
[self captureKeyboardFrameWithInfo:note.userInfo];
}
- (void)onKeyboardDidChangeFrame:(NSNotification *)note {
//Log("%@",note.userInfo);
//[self captureKeyboardFrameWithInfo:note.userInfo];
}
- (void)captureKeyboardFrameWithInfo:(NSDictionary *)info
{
CGRect _endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval _animationDuration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve animationCurve = (UIViewAnimationCurve)[info[UIKeyboardAnimationCurveUserInfoKey] integerValue];
[UIView animateWithDuration:_animationDuration delay:0 options:NgAnimationOptionsWithCurve(animationCurve) animations:^{
CGRect myFrame = self.frame;
myFrame.origin.y = _endFrame.origin.y - KeyBoardHeight;
self.frame = myFrame;
} completion:^(BOOL finished) {
/*if (_willHidden) {
dispatch_async(dispatch_get_main_queue(), ^{
[self removeFromSuperview];
});
_willHidden = NO;
}*/
}];
}
#pragma mark - TextField delegate
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([_delegate respondsToSelector:@selector(popKeyBoardHide)]) {
[_delegate popKeyBoardShow];
}
[self startListenKeyboard];
return YES;
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
return YES;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
self.content = textField.text;
[self endListenKeyboard];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
// [textField resignFirstResponder];
// if ([_delegate respondsToSelector:@selector(popKeyBoard:didClickSend:)]) {
// [_delegate popKeyBoard:self didClickSend:YES];
// _field.text = nil;
// if ([_delegate respondsToSelector:@selector(popKeyBoardHide)]) {
// [_delegate popKeyBoardHide];
// }
// }
[self didClickButton:nil];
return YES;
}
@end