我的UITableView
上有一个视图(在这种情况下UIViewController
,但这并不重要)我希望在键盘弹出时调整高度。
在自动布局中执行此操作的最佳方法是什么?目前在视图中我有这些限制:
我认为最快的方法是删除高度和底部空间约束,并在调用keyboardDidAppear
通知时调整代码中的实际视图大小,但有没有其他方法可以做到这一点?
答案 0 :(得分:17)
我会给你一个通用的想法,可能需要根据你的实际项目进行重新调整。
let notificationTokenKeyboardWillAppear = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { (note) in
guard let keyboardFrame = (note.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
self.scrollView?.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardFrame.size.height, right: 0.0)
}, completion: nil)
}
和
let notificationTokenKeyboardWillHide = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { (_) in
UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
self.scrollView?.contentInset = .zero
}, completion: nil)
}
注意事项1: scrollView
此处代表UIScrollView
的任何子集,例如UITableView
或UICollectionView
等等......
注意-2: 当您即将发布时,您需要通过调用removeObserver(_:)
方法手动删除令牌
我认为UITableView *_tableView
之前已在某处正确设置过。
- (void)viewDidLoad {
// ...
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
id _obj = [note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
CGRect _keyboardFrame = CGRectNull;
if ([_obj respondsToSelector:@selector(getValue:)]) [_obj getValue:&_keyboardFrame];
[UIView animateWithDuration:0.25f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[_tableView setContentInset:UIEdgeInsetsMake(0.f, 0.f, _keyboardFrame.size.height, 0.f)];
} completion:nil];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[UIView animateWithDuration:0.25f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[_tableView setContentInset:UIEdgeInsetsZero];
} completion:nil];
}];
// ...
}
注意: 如果您的 UITableView
不在屏幕底部,应在此行中优化> contentInset
值: [_tableView setContentInset:UIEdgeInsetsMake(0.f, 0.f, _keyboardFrame.size.height, 0.f)];
答案 1 :(得分:2)
保持身高限制并连接插座:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *CS_TableView_Height;
查看this tutorial的示例3。
使用NSNotificationCenter
- (void)viewWillAppear:(BOOL)animated
{
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
您可能还需要查看this question接受的答案,了解一些灵感。
所以最后,你应该得到这样的东西:
- (void)keyboardWillShow
{
self.CS_TableView_Height.constant = 500;//For example
[self.tableView setNeedsUpdateConstraints];
}
- (void)keyboardWillHide
{
self.CS_TableView_Height.constant = 568;// iPhone5 height
[self.tableView setNeedsUpdateConstraints];
}
答案 2 :(得分:0)
首先,你不应该添加一个上下限制和一个高度约束。如果屏幕大小发生变化,应用程序将崩溃(除非其中一个约束具有较低的优先级,在这种情况下它将被删除)。
其次,在您的keyboardDidAppear通知方法中,您只需将底部空间更改为superview的常量值并调用[myView setNeedsDisplay]
编辑:你不能在doneFirstResponder之后执行setNeedsDisplay。您添加self
作为keyboardWillShow
/ keyboardWillHide
次通知的观察者,并在该方法中更新约束并调用setNeedsDisplay
。
查看this apple post,Listing 5-1 Handling the keyboard notifications
和Listing 5-2 Additional methods for tracking the active text field
提供代码。