经过大量的试验和错误,我放弃了,并提出了这个问题。我见过很多人有类似的问题,但不能得到所有的答案工作正确。
我有一个由自定义单元格组成的UITableView。单元格由相邻的5个文本字段组成(有点像网格)。
当我试图滚动和编辑UITableView底部的单元格时,我不能设法让我的单元格正确地定位在键盘上方。
我看到过很多关于改变视图大小的回答……但到目前为止,没有一种效果很好。
谁能用一个具体的代码示例来阐明这样做的“正确”方式?
经过大量的试验和错误,我放弃了,并提出了这个问题。我见过很多人有类似的问题,但不能得到所有的答案工作正确。
我有一个由自定义单元格组成的UITableView。单元格由相邻的5个文本字段组成(有点像网格)。
当我试图滚动和编辑UITableView底部的单元格时,我不能设法让我的单元格正确地定位在键盘上方。
我看到过很多关于改变视图大小的回答……但到目前为止,没有一种效果很好。
谁能用一个具体的代码示例来阐明这样做的“正确”方式?
当前回答
Swift 3-4动画和键盘帧改变的解决方案:
首先,创建Bool类型:
// MARK: - Private Properties
private var isKeyboardShowing = false
其次,在系统键盘通知中添加观察者:
// MARK: - Overriding ViewController Life Cycle Methods
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame), name: .UIKeyboardWillChangeFrame, object: nil)
}
第三,准备动画功能:
func adjustTableViewInsets(keyboardHeight: CGFloat, duration: NSNumber, curve: NSNumber){
var extraHeight: CGFloat = 0
if keyboardHeight > 0 {
extraHeight = 20
isKeyboardShowing = true
} else {
isKeyboardShowing = false
}
let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight + extraHeight, right: 0)
func animateFunc() {
//refresh constraints
//self.view.layoutSubviews()
tableView.contentInset = contentInset
}
UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: [UIViewAnimationOptions(rawValue: UInt(curve))], animations: animateFunc, completion: nil)
}
然后添加target/action方法(由观察者调用):
// MARK: - Target/Selector Actions
func keyboardWillShow(notification: NSNotification) {
if !isKeyboardShowing {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardSize.height
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
adjustTableViewInsets(keyboardHeight: keyboardHeight, duration: duration, curve: curve)
}
}
}
func keyboardWillHide(notification: NSNotification) {
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
adjustTableViewInsets(keyboardHeight: 0, duration: duration, curve: curve)
}
func keyboardWillChangeFrame(notification: NSNotification) {
if isKeyboardShowing {
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
if let newKeyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = newKeyboardSize.height
adjustTableViewInsets(keyboardHeight: keyboardHeight, duration: duration, curve: curve)
}
}
}
最后,不要忘记在deinit或viewWillDisappear中删除观察者:
deinit {
NotificationCenter.default.removeObserver(self)
}
其他回答
在viewdidload
-(void)viewdidload{
[super viewdidload];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
-(void)keyboardWillChange:(NSNotification*)sender{
NSLog(@"keyboardwillchange sender %@",sender);
float margin=0 // set your own topmargin
CGFloat originY = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
if (originY >= self.view.frame.size.height){
NSLog(@"keyboardclose");
[tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, self.view.frame.size.height-margin)];
}else{
NSLog(@"keyobard on");
float adjustedHeight = self.view.frame.size.height - margin - (self.view.frame.size.height-originY);
[tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, adjustedHeight)];
}
}
如果你使用Three20,那么使用autoresizesForKeyboard属性。只要在视图控制器的-initWithNibName:bundle方法中设置
self.autoresizesForKeyboard = YES
这涉及到:
监听键盘通知并调整表视图的框架 滚动到第一个响应器
搞定了。
这个解决方案为我工作,请注意这一行
[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];
您可以更改160值以使其与您的工作相匹配
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect bkgndRect = activeField.superview.frame;
bkgndRect.size.height += kbSize.height;
[activeField.superview setFrame:bkgndRect];
[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
tableView.contentInset = contentInsets;
tableView.scrollIndicatorInsets = contentInsets;
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect bkgndRect = activeField.superview.frame;
//bkgndRect.size.height += kbSize.height;
[activeField.superview setFrame:bkgndRect];
[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}
另一个简单的方法(只适用于一个部分)
//cellForRowAtIndexPath
UItextField *tf;
[cell addSubview:tf];
tf.tag = indexPath.row;
tf.delegate = self;
//textFieldDidBeginEditing:(UITextField *)text
[[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES];
以下是我如何做到这一点的,这是Sam Ho和Marcel W的回答,以及我自己对蹩脚代码的一些错误修复。我用的是UITableViewController。当键盘显示时,表格现在可以正确地调整大小。
1)在viewDidLoad我添加:
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
2)我忘记在viewWillAppear和awakeFromNib中调用超等价物。我把这些加回来了。