我们在TextField输入时经常会出现被虚拟键盘挡住的现象,下面是具体的解决办法
//要用到textfield的代理
@interface ScrollerViewController ()<UITextFieldDelegate> {
BOOL keyboardIsShown;//键盘是否出现
CGPoint offset;//记录在键盘出现前,scrollview的contentOffset
}
@property (nonatomic, retain) UIScrollView *scrollView;
@property (nonatomic, retain) UITextField *textField;
@end
首先设置scrollview和加载textField
- (void)viewDidLoad
{
//设置ScrollView
scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.scrollView.zoomScale = 1.0;
self.scrollView.contentSize = CGSizeMake(320, 1128);
self.scrollView.contentOffset = CGPointMake(0, 0);
self.scrollView.bounces = NO;
//设置显示textField
for (int i = 0; i < 10; i++) {
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(20, 20 + i * 38, 70, 30)];
label.text = [NSString stringWithFormat:@"label%i",i + 1];
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 20 + i * 38, 200, 30)];
self.textField.backgroundColor = [UIColor whiteColor];
self.textField.delegate = self;
self.textField.borderStyle = UITextBorderStyleRoundedRect;
[self.scrollView addSubview:label];
[self.scrollView addSubview:self.textField];
[label release];
[self.textField release];
}
[self.view addSubview:self.scrollView];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
在View出现之前,注册两个通知。它能通知你什么时候keyboard出现或消失。
- (void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
[super viewWillAppear:animated];
}
当任何textField被点击时textFieldDidBeginEditing:被激活,你可以保存一个正在被点击textField的拷贝。
- (void)textFieldDidBeginEditing:(UITextField *)textFieldView{
textField = textFieldView;
}
当点击keyboard上的Return键时textFieldShouldReturn:方法会响应
- (BOOL)textFieldShouldReturn:(UITextField *)textFieldView{
[textFieldView resignFirstResponder];
returnNO;
}
当keyboard隐藏,结束输入时textFieldDidEndEditing:方法会被textfield会被设为nil。
- (void)textFieldDidEndEditing:(UITextField *)textFieldView{
textField = nil;
}
当键盘出现时,通过notification设置,keyboardDidShow:方法开始响应。方法中最重要的是获取键盘的高度,例如输入中文时,键盘会多出一行选字提示,高度就会发生变化,所以不能设成固定的216。然后重新设置ScrollView的frame,将textField滚动到可见位置。
如果键盘已经出现时,点击另一个textField,这个方法会自动退出。因为keyboardIsShown已经设为YES。如果点击的textField有部分隐藏,它会自动滚动到可见区域。
- (void)keyboardDidShow:(NSNotification *)notification{
//当键盘已经出现
if (keyboardIsShown) {
return;
}
NSDictionary *info = [notification userInfo];
//获取keyboard的size
NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [self.view convertRect:[aValue CGRectValue] fromView:nil];
NSLog(@"%f", keyboardRect.size.height);
//获取scrollView的contentOffset,当前的滚动位置
offset = self.scrollView.contentOffset;
//当键盘存在时,重新设置scrollView的size
CGRect viewFrame = [self.scrollView frame];
viewFrame.size.height -= keyboardRect.size.height;
self.scrollView.frame = viewFrame;
//将textField滚动到可见区域
CGRect textFieldRect = [self.textField frame];
[self.scrollView scrollRectToVisible:textFieldRect animated:YES];
keyboardIsShown = YES;
}
当键盘消失时,keyboardDidHide:开始响应。还原ScrollView的frame
- (void)keyboardDidHide:(NSNotification *)notification{
//获取键盘size
NSDictionary* info = [notification userInfo];
NSValue* aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [self.view convertRect:[aValue CGRectValue] fromView:nil];
//重新设置scrollView的size,使它还原到初始size
CGRect viewFrame = [self.scrollView frame];
viewFrame.size.height += keyboardRect.size.height;
self.scrollView.frame = viewFrame;
//还原滚动位置
self.scrollView.contentOffset = offset;
keyboardIsShown = NO;
}
最后在View消失前,移除两个通知
- (void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}