Reputation: 4764
I have a tableview with a textview for entering text immediately below it similar to Apple Messages. When the user begins to enter text and the keyboard appears, I want the following behavior similar to IOS Messages.
If the keyboard will not cover anything, the visible part of the tableview remains unchanged.
If the keyboard will cover something, the tableview moves up just enough so that its bottom-most filled cell is just above the keyboard.
Because I'm using autolayout, I currently have a constraint between the tableview and the textview below it. Also, the project has IQKeyboard which manages a lot of other views involving textfields and textviews.
The constraint combined with IQKeyboard accomplishes 2. When the keyboard appears, the keyboard pushes the textview up. The textview pushes the tableview up. So if the tableview is fully populated, you see the last cell of the tableview above the textview above the keyboard as desired.
However, 2. is not working.
if the tableview is not filled, the keyboard pushes up the textview which pushes up the tableview so that you longer see the top of the tableview.
I have tried adjusting the contentOffset property of the tableview when the Keyboard Shows and this sort of works but the tableview initially moves up before coming back down. I think this is because the notification to change the offset property does not fire until after the keyboard has begun to move up.
I also tried adjusting the tableview height to its content but this causes the textview to expand to fill the difference due to constraints.
Content offset approach - problem is that content offset adjusts too late
//register for keyboard notifications and in handler:
if let infoKey = notification.userInfo?[UIKeyboardFrameEndUserInfoKey],
let rawFrame = (infoKey as AnyObject).cgRectValue {
let keyboardFrame = view.convert(rawFrame, from: nil)
self.heightKeyboard = keyboardFrame.size.height
UIView.animate(withDuration: 0.2, animations: {
self.tableView.contentInset = UIEdgeInsetsMake(self.heightKeyboard!, 0, 0, 0);
})
}
Can anyone suggest a way to mimic the behavior of Apple Messages? Thanks in advance for any suggestions.
Upvotes: 0
Views: 2082
Reputation: 77423
One approach:
@IBOutlet
for the textField's bottom constraintWhen the keyboard is shown, change the .constant
of the textField's bottom constraint to the height of the keyboard view.
This will move the textField up, and because it's top is constrained to the bottom of the tableView, it will also move the tableView's bottom edge up.
Then scroll to the bottom of the tableView.
Layout:
Initial hierarchy, with 20 rows (scrolled to the bottom):
Hierarchy view (tableView background color set to green, so we can see its frame):
View after the keyboard is shown:
Hierarchy after the keyboard is shown:
Little tough to see from static screen caps, but the frame of the green rectangle (the tableView background) is now shorter... the user can still scroll up and down to see all the rows, but the bottom of the tableView is still constrained to the top of the textField.
When you the keyboard is dismissed, set the .constant
of the textField's bottom constraint back to Zero.
You can see a full, working example project up on GitHub: https://github.com/DonMag/KBAdjust
Upvotes: 1