這個問題很常見,相信大家也遇到過,網上的解決辦法也一大堆。下面說說我遇到的問題,在此記錄一下。
1.如果是普通的頁面,是指在controller上直接鋪控件UITextField(比如登錄、註冊頁等),要求不是很高的可以選擇在鍵盤彈出時,view整體上移(不管鍵盤是否遮擋),代碼如下:
RegisterViewController.m
@interface RegisterViewController ()<UITextViewDelegate>
{
CGFloat keyboardHeight;//記錄鍵盤的高度
}
@property (nonatomic) CGRect viewFrame; //記錄當前view的frame
@end
@implementation RegisterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.viewFrame = self.view.frame;//注意這一句,要先記錄一下頁面frame並賦值
[self addNotification];//註冊鍵盤彈出、消失的通知
}
-(void)addNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
//鍵盤彈出的時候
-(void)keyboardWillShow:(NSNotification *)notificaiton
{
CGRect keyboardFrame = [[notificaiton.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardHeight = keyboardFrame.size.height;
CGPoint point = self.view.center;
point.y -= 120;//120是根據你實際的需求,不一定是多少
[UIView animateWithDuration:0.3f animations:^{
self.view.center = point;
}];
}
//鍵盤消失的時候,回覆原來的frame
-(void)keyboardWillHide:(NSNotification *)notificaiton
{
self.view.frame = self.viewFrame;
}
//養成好習慣移除通知
- (void)dealloc{
//移除鍵盤通知監聽者
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
@end
2.下面這種情況是本文說的重點,也非常常見。大家肯定經常會用到tableview頁面,然後在tableviewCell裏面有UITextField控件,這時候也肯定會遇到遮擋的問題,大家首先想法就是UITextField輸入完之後就回收鍵盤(可以點擊空白處回收鍵盤),這樣的話體驗不太好,造成用戶看不到正在給哪一個UITextField輸入內容。思路:你的控件(也就是UITextField相對於最外層view的位置(y座標)跟彈出鍵盤相對於最外層view的位置(y座標),相比較,看是否遮擋),如果遮擋了計算出遮擋的高度,然後設置最外層視圖的frame,往上移動到大於等於遮擋遮住的高度即可。下面就是解決辦法,不多說,直接上代碼,如下:
首先TableViewCell.h
typedef void (^CellTextFieldValueChangedBlock)(UITextField *tf);//爲什麼參數有UITextField 下面在controller會有講解,該block是爲了textField回調用
@interface TableViewCell : UITableViewCell<UITextFieldDelegate>
@property(nonatomic,strong)UITextField *contentField;
@property(nonatomic,copy)CellTextFieldValueChangedBlock block;
-(void)cellFieldBlock:(CellTextFieldValueChangedBlock)block;
TableViewCell.m
在你創建textFiled的時候,給textField加上點擊事件
[self.contentField addTarget:self action:@selector(textField:) forControlEvents:UIControlEventEditingDidBegin];//注意是UIControlEventEditingDidBegin,至於爲什麼就不講解了
//下面就是一個簡單的block回傳
-(void)textField:(UITextField *)textField{
if (self.block) {
self.block(textField);
}
}
-(void)cellFieldBlock:(CellTextFieldValueChangedBlock)block{
self.block = block;
}
接下來到我們的controller了,
@interface InfoViewController ()<UITableViewDelegate, UITableViewDataSource,UIGestureRecognizerDelegate,UITextFieldDelegate>
@property(nonatomic ,strong) UITextField * firstResponderTextF;//記錄將要編輯的輸入框,從cell裏傳過來的UITextField就用到了
@end
@implementation InfoViewController
//省略其他代碼直接看重點,tableview的代理方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"ResetCell";
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.contentField.delegate = self;
WEAK_SELF(weakSelf)
[cell cellFieldBlock:^(UITextField * _Nonnull tf) {
weakSelf.firstResponderTextF = tf;//記錄編輯的textField,稍後再鍵盤彈出的方法裏有用
[weakSelf addNotification];//同樣註冊鍵盤彈出、消失的通知,這裏爲什麼在回調裏註冊相信你試一下就知道了
}];
return cell;
}
#pragma mark : UIKeyboardWillShowNotification/UIKeyboardWillHideNotification
- (void)keyboardWillShow:(NSNotification *)notification{
CGRect rect = [self.firstResponderTextF.superview convertRect:self.firstResponderTextF.frame toView:self.tableView];//獲取當前輸入的textField相對於self.tableView的位置
//會有人問爲什麼是tableview而不是view,因爲tableview是最外層,你的textField也是加在tableview上
CGRect keyboardRect = [[notificaiton.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];//獲取鍵盤高度
keyboardRect = [self.tableView convertRect:keyboardRect fromView:nil];//獲取鍵盤相對於self.tableView的frame
CGFloat keyboardTop = keyboardRect.origin.y;//用於跟textField的y比較
NSNumber * animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];//獲取鍵盤彈出動畫時間值
NSTimeInterval animationDuration = [animationDurationValue doubleValue];
if (keyboardTop < CGRectGetMaxY(rect)) {//如果鍵盤蓋住了輸入框
CGFloat gap = keyboardTop - CGRectGetMaxY(rect) - 10;//計算需要往上移動的偏移量(輸入框底部離鍵盤頂部爲10的間距)
WEAK_SELF(weakSelf)
[UIView animateWithDuration:animationDuration animations:^{
weakSelf.tableView.frame = CGRectMake(weakSelf.tableView.frame.origin.x, gap, weakSelf.tableView.frame.size.width, weakSelf.tableView.frame.size.height);
}];
}
}
- (void)keyboardWillHide:(NSNotification *)notification{
NSDictionary *userInfo = [notification userInfo];
NSNumber * animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];//獲取鍵盤隱藏動畫時間值
NSTimeInterval animationDuration = [animationDurationValue doubleValue];
if (self.tableView.frame.origin.y < 0) {//如果有偏移,當影藏鍵盤的時候就復原
WEAK_SELF(weakSelf)
[UIView animateWithDuration:animationDuration animations:^{
weakSelf.tableView.frame = CGRectMake(weakSelf.tableView.frame.origin.x, 0, weakSelf.tableView.frame.size.width, weakSelf.tableView.frame.size.height);
}];
}
}
-(void)addNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
@end
上面就是遇到問題的解決辦法,在此記錄一下,同時鞏固一下便於以後使用。
另附上,tableview點擊空白處回收鍵盤代碼,如下:
在controller裏初始化的時候 ,一般都在viewDidLoad方法
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesturedAction:)];
tap.delegate = self;//注意代理
[self.tableView addGestureRecognizer:tap];
#pragma mark -UIGestureRecognizer
-(void)tapGesturedAction:(UIGestureRecognizer *)gesture{
[self.tableView endEditing:YES];
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
NSLog(@"-----%@",NSStringFromClass([touch.view class]));
//如果某些地方不希望回收鍵盤,可以用NSStringFromClass([touch.view class])來處理,具體需求具體分析
return YES;
}