UIScrollViewKeyboardDismissModeInteractive change table height with keyboard
Within the limits UIViewController
that I have set
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive
.
This is great because the user can drag the keyboard out of the table.
However, the tableview maintains the current height when dragging the keyboard. It looks weird because it leaves white space between the keyboard and the scroll.
How can I persistently track the keyboard frame to resize the table view when the user drags the keyboard? I've tried using UIKeyboardWillChangeFrameNotification
but seems to only be called after the user has finished dragging.
source to share
In your table view, you shouldn't change the height to accommodate the keyboard.
Instead, the keyboard should be represented on the table in the form of a table, and you have to set the properties contentInset
and scrollIndicatorInsets
in the table view to the contents of the bottom of the table was not closed keyboard. You need to update the scroll inserts whenever the keyboard is presented or dismissed.
You don't need to do anything when the keyboard is tilted interactively, because the contents of the table should already scroll down when the keyboard goes out of sight.
source to share
I would have preferred it not to be the accepted answer, but for those of you out there that had problems with this too, which worked for me.
-
Create your own UIView subclass.
-
In your subclass method,
willMoveToSuperview:
add the KVO observer to the supervisorcenter
on iOS 8 andframe
smaller versions of iOS (remember to remove the old observer, you might want to use an instance variable to track this). -
In your view, the controller adds a helper accessory view of height 0.0 to the view controller using a class override
inputAccessoryView
. Use your own subclass for thisUIView
. -
Go back to subclass in
observeValueForKeyPath:...
, writeframe
to viewview, it should be a frameUIKeyboard
. -
Use
NSNotificationCenter
or some other means to pass thisframe
back to your view controller for processing.
This is a painful process and is not guaranteed to work in future versions of iOS. Chances are tons of edge cases will show up later, since I just built this, but this is a good start. If anyone has a better idea, I will happily mark your answer as correct.
source to share
This is what I ended up with, when using notification I use a delegate:
protocol MyCustomViewDelegate {
func centerChanged(center: CGPoint)
}
class MyCustomView: UIView{
private var centerContext = 0
var delegate: MyCustomViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func willMoveToSuperview(newSuperview: UIView?) {
super.willMoveToSuperview(newSuperview)
guard let newSuperview = newSuperview else {
self.superview?.removeObserver(self, forKeyPath: "center")
return
}
let options = NSKeyValueObservingOptions([.New, .Old])
newSuperview.addObserver(self, forKeyPath: "center", options: options, context: ¢erContext)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
//print("CHANGE",keyPath)
if context == ¢erContext {
guard let center = superview?.center else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
return
}
delegate?.centerChanged(center)
} else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
}
source to share