Reputation: 117
I'm working on an iOS app and currently all my elements are in a scroll view and when the keyboard is present I move the view up 250 pts. This solved my problem but the keyboard is always a different size per device.
How could I detect how far from the bottom of the screen my text field is and how tall the keyboard is?
Upvotes: 0
Views: 1294
Reputation: 7434
I'm currently work on this and found a solution. First you need to add a notification to the view controller to identify whether the keyboard is on or not. For that you need to register this notification in viewDidLoad().
override func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardDidShow:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}
And also don't forget to remove this notification, when the view controller removed from the view. So remove this notification on viewDidDisappear().
override func viewDidDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillChangeFrameNotification, object: nil)
}
And the final thing is to manage the scroll view when the keyboard is on or off. So first you need to identify the keyboard height.Then for pretty smooth animation, you can use keyboard animation mood and duration time to animate your scroll view.
func keyboardDidShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height {
//isKeyboardActive = false
UIView.animateWithDuration(duration,
delay: NSTimeInterval(0),
options: animationCurve,
animations: {
// move scroll view height to 0.0
},
completion: { _ in
})
} else {
//isKeyboardActive = true
UIView.animateWithDuration(duration,
delay: NSTimeInterval(0),
options: animationCurve,
animations: {
// move scroll view height to endFrame?.size.height ?? 0.0
},
completion: { _ in
})
}
}
}
Upvotes: 1
Reputation: 2459
@noir_eagle answer seems right.
But there may be is a simpler solution. Maybe you could try using IQKeyboardManager
. It allows you to handle these keyboard things in a simple and seamless way.
I think you really should, at least, spend few minutes looking at it.
Upvotes: 0
Reputation: 864
You should observe the notification for showing and hiding the keyboard. And after that you can get the exact keyboard size and either shift or change the content insets of your scroll view. Here's a sample code:
extension UIViewController {
func registerForKeyboardDidShowNotification(scrollView: UIScrollView, usingBlock block: (NSNotification -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
let userInfo = notification.userInfo!
let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey]?.CGRectValue.size
let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, keyboardSize!.height, scrollView.contentInset.right)
scrollView.scrollEnabled = true
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
block?(notification)
})
}
func registerForKeyboardWillHideNotification(scrollView: UIScrollView, usingBlock block: (NSNotification -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillHideNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, 0, scrollView.contentInset.right)
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
scrollView.scrollEnabled = false
block?(notification)
})
}
}
extension UIScrollView {
func setContentInsetAndScrollIndicatorInsets(edgeInsets: UIEdgeInsets) {
self.contentInset = edgeInsets
self.scrollIndicatorInsets = edgeInsets
}
}
And in your UIViewController
in which you want to shift the scrollview, just add next lines under the viewDidLoad()
function
override func viewDidLoad() {
super.viewDidLoad()
registerForKeyboardDidShowNotification(scrollView)
registerForKeyboardWillHideNotification(scrollView)
}
Upvotes: 2