我在调整tableview大小并在iPad上以表单形式显示时,遇到了一些困难。当键盘出现时,我无法滚动到活动文本字段。在iPhone上,这个问题没有出现,因为我不需要考虑表单视图的偏移量 - 我只需将tableview的底部contentInset更改为键盘高度即可。然而,在iPad上这种方法行不通,因为表单视图及其tableview并未占据整个屏幕。
有什么最佳方法来计算新的tableview底部contentInset应该是多少?
有什么最佳方法来计算新的tableview底部contentInset应该是多少?
好的,我自己也遇到了这个问题。我创建了一个适用于所有情况的解决方案(不仅仅适用于以表单形式呈现的视图控制器)。解决方案使用Swift 3编写,所以您仍然需要将其转换为Objective-C,但是如果您仔细阅读注释,这应该不是问题。
该解决方案的关键是在键盘动画完成并且表单已经处于新位置时更新tableView(或scrollView)插入内容。
在您的UIViewController子类中添加:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: .UIKeyboardWillHide, object: nil)
}
这将在键盘显示/隐藏时添加一个观察器。我们还需要取消订阅这些通知,否则应用程序将崩溃:
deinit {
NotificationCenter.default.removeObserver(self)
}
最后,最重要的代码:
func getTableViewInsets(keyboardHeight: CGFloat) -> UIEdgeInsets {
// Calculate the offset of our tableView in the
// coordinate space of of our window
let window = (UIApplication.shared.delegate as! AppDelegate).window!
let tableViewFrame = tableView.superview!.convert(tableView.frame, to: window)
// BottomInset = part of keyboard that is covering the tableView
let bottomInset = keyboardHeight
- ( window.frame.height - tableViewFrame.height - tableViewFrame.origin.y )
// Return the new insets + update this if you have custom insets
return UIEdgeInsetsMake(
tableView.contentInset.top,
tableView.contentInset.left,
bottomInset,
tableView.contentInset.right
)
}
func keyboardWillChangeFrame(_ notification: Notification){
guard let info = (notification as NSNotification).userInfo else {
return
}
guard let animationDuration = info[UIKeyboardAnimationDurationUserInfoKey] as? TimeInterval else {
return
}
// Default: keyboard will hide:
var keyboardHeight: CGFloat = 0
if notification.name == .UIKeyboardWillChangeFrame {
// The keyboard will show
guard let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
keyboardHeight = keyboardFrame.cgRectValue.height
}
let contentInsets = getTableViewInsets(keyboardHeight: keyboardHeight)
UIView.animate(withDuration: animationDuration, animations: {
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
}, completion: {(completed: Bool) -> Void in
// Chances are the position of our view has changed, (form sheet)
// so we need to double check our insets
let contentInsets = self.getTableViewInsets(keyboardHeight: keyboardHeight)
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
})
}
let bottomInset = keyboardHeight - (window.frame.maxY - tableViewFrame.maxY)
。 - user1046037UIKeyboardWillChangeFrame
而不是 UIKeyboardWillShow
? - Radek Wilczak首先,感谢Simon Backx,我在我的真实项目中使用了他的方法。它有效,但有一些情况没有完全考虑到。我对他的答案进行了优化。我原本想在他的答案下面添加评论,但我们没有足够的声望来添加评论。我只能创建一个新的答案,希望这个答案可以帮助其他人。
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
contentInsets
private func calculateTableViewContentInsets(keyboardHeight: CGFloat) -> UIEdgeInsets {
let window = (UIApplication.shared.delegate as! AppDelegate).window!
let tableViewFrame = tableView.superview!.convert(tableView.frame, to: window)
let bottomInset = keyboardHeight
- (window.frame.height - tableViewFrame.height - tableViewFrame.origin.y)
- tableView.safeAreaInsets.bottom
var newInsets = tableView.contentInset
newInsets.bottom = bottomInset
return newInsets
}
@objc private func keyboardWillChangeFrame(_ sender: Notification) {
guard let userInfo = sender.userInfo else { return }
guard let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
guard let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
let keyboardHeight = keyboardFrame.height
let contentInsets = calculateTableViewContentInsets(keyboardHeight: keyboardHeight)
UIView.animate(withDuration: duration, animations: {
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
}, completion: { _ in
let contentInsets = self.calculateTableViewContentInsets(keyboardHeight: keyboardHeight)
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
})
}
@objc private func keyboardWillHide(_ sender: Notification) {
guard let userInfo = sender.userInfo else { return }
guard let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
UIView.animate(withDuration: duration) {
self.tableView.contentInset.bottom = 0
self.tableView.scrollIndicatorInsets.bottom = 0
}
}
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomMargin;
为UIKeyboardWillShowNotification
添加观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
以及实际的方法
-(void)keyboardWillShow:(NSNotification*)notification {
[self.view layoutIfNeeded];
NSDictionary* userInfo = [notification userInfo];
CGRect keyboardFrameEnd;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameEnd]; //getting the frame of the keyboard
//you can get keyboard animation's duration and curve with UIKeyboardAnimationCurveUserInfoKey and UIKeyboardAnimationDurationUserInfoKey if you want to animate it
//calculate the new values of the constraints of your UITableView
//for the example, the new value will be the keyboard height
self.bottomMargin.constant = keyboardFrameEnd.size.height;
[self.view layoutIfNeeded];
}
我在这篇帖子中发布了一个演示如何完成此操作的链接:
iOS 7 iPad方向问题,在UITextField上键盘出现后视图向上移动
它还包括一个keyboardWillShow
函数,但它可以与iOS 8兼容:
-(void)onKeyboardWillShow:(NSNotification*)notification
{
// The user has turned on the onscreen keyboard.
//
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrame = [kbFrame CGRectValue];
keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil];
CGFloat keyboardHeight = keyboardFrame.size.height;
}
我发现在iOS 8.x中,如果我没有使用convertRect
函数,有时iPad在横屏模式下会报告键盘高度为1024像素。